web-dev-qa-db-ja.com

これらのクラスをAutofacに登録する方法

Iocコンテナとしてautofacを使用しています。私には3つのクラスがあります:

class Service
{
     public Service(Repository rep,UnitOfWork context){}

}

Class Repository
{
     public Repository(UnitOfWork context){}
}

class UnitOfWork{}

サービスとリポジトリには、UnitOfWorkの同じインスタンスが必要です

どうやってするか? XmlConfigurationでそれを作成する方法

11
DotDot

EDIT:これを読み間違えて、autofacを使用して依存関係を登録する方法についての質問だと思いました。同じUnitOfWorkを維持したい場合は、インスタンスの存続期間を何かにスコープする必要があります。これをASP.NETまたはWCFアプリケーションで使用している場合は、次のように依存関係を登録できます。

_typeBuilder.RegisterType<UnitOfWork>().InstancePerLifetimeScope();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();
_

Autofacのようなコンテナを使用するために最初に行う必要があるのは、すべての依存関係を登録することです。 Autofacでは、いくつかの方法でそれを行うことができますが、それらはすべてContainerBuilderの使用に依存しています。 ContainerBuilderは拡張メソッドに依存しているため、Autofac名前空間にusingステートメントがあることを確認してください。

ファクトリメソッドを明示的に定義できます:

_// Explicitly 
var builder = new ContainerBuilder();
builder.Register<UnitOfWork>(b => new UnitOfWork());
builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));
builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));
_

ContainerBuilderを使用して、Register<>()メソッドにアクセスし、サービスインターフェイスを提供します(これは、コンテナにサービスを要求する方法です)。この場合、インターフェイスは使用せず、実際のタイプのみを使用します。コンテナにUnitOfWorkを要求するたびに、ファクトリメソッドnew UnitOfWork()を使用してコンテナを生成します。実生活では、おそらくIUnitOfWorkを要求するでしょう。これはすべて少し冗長になる可能性がありますが、依存関係の作成にカスタムロジックが必要な場合に非常に便利です。

他の依存関係コンテナーと同じようにビルダーを使用して、タイプを登録するだけです。

_// Implicitly
var typeBuilder = new ContainerBuilder();
typeBuilder.RegisterType<UnitOfWork>();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();
_

このアプローチは、クラスの構築に必要なすべての依存関係を登録することに依存しています。次に、コンテナーはリフレクションを使用してコンストラクター引数を解決します。引数が登録されていない場合、コンテナは解決できなかったタイプの例外をスローします。この場合、サービスはUnitOfWorkRepositoryに依存しています。 RepositoryUnitOfWorkに依存しています。これらの依存関係は、コンストラクター引数として表されます。コンテナからRepositoryまたはServiceをリクエストするには、すべての依存関係を登録する必要があります

構成アプローチを使用できます。

App.configファイルを使用している場合は、次のように構成ファイルを定義できます。

_<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
  </configSections>

  <autofac defaultAssembly="AutoFacTest">
    <components>
      <component
              type="AutoFacTest.Repository, AutoFacTest"
              service="AutoFacTest.Repository" />

      <component
               type="AutoFacTest.UnitOfWork, AutoFacTest"
               service="AutoFacTest.UnitOfWork" />

      <component
              type="AutoFacTest.Service, AutoFacTest"
              service="AutoFacTest.Service" />
    </components>
  </autofac>
</configuration>
_

まず、構成セクションを定義する必要があることに注意してください(_<ConfigSections>_に注意してください)。次に、すべての依存関係を定義する_<autofac>_セクションを作成できます。表記は非常に単純で、基本的にすべての依存関係に対して_<component>_を作成します。各コンポーネントには、要求されるタイプを定義するservice属性があります。サービスのインスタンスが要求されたときに作成されるオブジェクトを定義するtype属性もあります。これはbuilder.Register<UnitOfWork>(b => new UnitOfWork())に類似しています。ここで、UnitOfWorkは要求されたサービス(この場合は)であり、作成されるタイプでもあります。

構成を使用してビルダーを作成するには、ConfigurationSettingsReader()を使用します

_// Config
var configBuilder = new ContainerBuilder();
configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));
_

構成セクションの名前(この場合はautofac)を渡す必要があります。依存関係を構成したら、コンテナーを作成する必要があります。 ContainerBuilderには、これを行うためのメソッドが含まれています。

_var container = builder.Build();
var typeContainer = typeBuilder.Build();
var configContainer = configBuilder.Build();
_

コンテナを取得したら、サービスのインスタンスをリクエストできます。

_container.Resolve<Service>().DoAwesomeness();
typeContainer.Resolve<Service>().DoAwesomeness();
configContainer.Resolve<Service>().DoAwesomeness();
_

完全なプログラム:

_using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
using Autofac.Configuration;

namespace AutoFacTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Explicitly 
            var builder = new ContainerBuilder();
            builder.Register<UnitOfWork>(b => new UnitOfWork());
            builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));

            builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));

            // Implicitly
            var typeBuilder = new ContainerBuilder();
            typeBuilder.RegisterType<UnitOfWork>();
            typeBuilder.RegisterType<Repository>();
            typeBuilder.RegisterType<Service>();

            // Config
            var configBuilder = new ContainerBuilder();
            configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));

            var container = builder.Build();
            var typeContainer = typeBuilder.Build();
            var configContainer = configBuilder.Build();


            container.Resolve<Service>().DoAwesomeness();
            typeContainer.Resolve<Service>().DoAwesomeness();
            configContainer.Resolve<Service>().DoAwesomeness();
            Console.Read();
        }
    }

    public class Repository
    {
        private readonly UnitOfWork _unitOfWork;
        public Repository(UnitOfWork uow)
        {
            _unitOfWork = uow;
        }

        public void PrintStuff(string text)
        {
            Console.WriteLine(text);
        }
    }

    public class Service
    {
        private readonly Repository _repository;
        private readonly UnitOfWork _unitOfWork;

        public Service(Repository repo, UnitOfWork uow)
        {
            _repository = repo;
            _unitOfWork = uow;
        }
        public void DoAwesomeness()
        {
            _repository.PrintStuff("Did awesome stuff!");
            _unitOfWork.Commit();
        }
    }

    public class UnitOfWork
    {
        public bool Commit()
        {
            return true;
        }
    }


}
_
31
JaySilk84