12

autofac を Ioc コンテナーとして使用しています。私は3つのクラスを持っています:

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

}

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

class UnitOfWork{}

Service と Repository には UnitOfWork の同じインスタンスが必要です

どうやってするか?および XmlConfiguration でそれを記述する方法

4

1 に答える 1

32

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

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

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

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

// 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>();

このアプローチは、クラスを構築するために必要なすべての依存関係を登録することに依存しています。その後、コンテナーはリフレクションを使用して、コンストラクターの引数を解決します。引数が登録されていない場合、コンテナーは解決できなかった型の例外をスローします。この場合、サービスは と に依存しUnitOfWorkていRepositoryます。Repositoryにも依存していUnitOfWorkます。これらの依存関係は、コンストラクターの引数として表されます。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>for every 依存関係を作成します。各コンポーネントには、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;
        }
    }


}
于 2012-07-26T03:58:00.087 に答える