2

問題は次のとおりです。私は汎用リポジトリを使用するソリューションに取り組んでおり、リポジトリは正常に動作します。問題は、コントローラーのコンストラクターに依存関係を挿入できるようにするために、コードをリファクタリングしようとしているということです。なぜ私はこれを達成したいのですか?, ソリューションはTDDを使用しています.アプリケーションのテスト方法を簡単にしたい. 私たちが実際に行っているように偽物を作成したくはありません.EFリポジトリの利点を実際に利用し、FakeRepository(レベルエンティティで変更を行う)と実際のリポジトリを使用してコンパイル時に解決したいのではありません.データベースへの変更。

永続化テクノロジとして EF を使用しています。

これらの行はリポジトリを表します

public class Repository<T> : IRepository<T> where T
                                : class, IEntity
{
    private readonly DbSet<T> dbset;
    private readonly DbContext _context;

    public Repository(DbContext context)
    {
        _context = context;
        dbset = context.Set<T>();
    }

    public void Add(T entity)
    {
        //Some logic...
    }

    public void Update(T entity)
    {
        //Some logic...
    }

    //more methods...

}

これらの行は、偽のリポジトリを表しています

    public class FakeRepository<T> : IRepository<T> where T
                                : class, IEntity
{
    private readonly DbSet<T> dbset;
    private readonly DbContext _context;

    public FakeRepository(DbContext context)
    {
        _context = context;
        dbset = context.Set<T>();
    }

    public void Add(T entity)
    {
        //Some logic...
    }

    public void Update(T entity)
    {
        //Some logic...
    }

    public void Remove(T entity)
    {
        //Some logic...
    }

    //more methods...
}

これらの行は、リポジトリのインターフェイス コントラクトを表します。

public interface IRepository<T>
                    where T : class, IEntity
{
    void Add(T entity);
    void Remove(T entity)
    void Remove(T entity);
    //more methods...
}

これは、コンストラクターが前の型のジェネリックを期待するコントローラーの例です。

public class DemoController : Controller
{
    private readonly IRepository<IEntity> _repository;
    public DemoController(IRepository<IEntity> repository)
    {
        _repository = repository;
    }

    public ViewResult Index()
    {
        return View(_repository.FindAll());
    }

}

問題は、Autofac コンテナーに型を登録するにはどうすればよいかということです。これを達成する方法について多くのフォーラムを見てきましたが、このニーズを解決するアプローチは見つかりませんでした。

これをglobal.asaxで試しました:

    protected void Application_Start()
    {
        ConfigureIoC();
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

    private static void ConfigureIoC()
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(Global).Assembly);

        //At this section the dependencies are added in order to resolve Types.
        builder.RegisterType<MyController>().InstancePerHttpRequest();

        builder.RegisterType<MyContext>().As<DbContext>();
        builder.RegisterType<Repository<Entity>>().As<IRepository<IEntity>>();

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }

また、個々の型を登録しようとしましたが、autofac は単にコントローラー コンストラクターを解決する方法を知りません。

前もって感謝します!。

4

2 に答える 2

4

は具体的なエンティティではなく、おそらく具体的なエンティティ ( など) を必要とIRepository<IEntity>するDemoControllerため、非常に奇妙です。具体的なにマップする必要があるため、次の登録が必要です。IEntityDemoControllerCustomerIRepository<T>Repository<T>

builder.RegisterGeneric(typeof(Repository<>))
    .As(typeof(IRepository<>));

おそらくDbContext、Web リクエストごとに、またはライフタイム スコープで を登録する必要があります。そして、MyControllerasを登録するのは奇妙に思えPerHttpRequestます。

于 2012-04-27T07:36:27.143 に答える
1

アドバイスありがとうスティーブン。ドキュメントと他のいくつかのブログを見て、私が共有している解決策を見つけました。また、私はあなたの代替手段を試して、どちらが他のものよりも速いかを確認します。

ジェネリック フォーカスに基づいてコンストラクター インジェクションを解決するためのコードは次のとおりです。

    protected void Application_Start()
    {
        ConfigureIoC();
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

    private static void ConfigureIoC()
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(Global).Assembly);

        //First we register the types for DemoController.
        builder.RegisterType<Repository<Entity>>().As<IRepository<IEntity>>();
        //Then we register the controller itself resolving/indicating the target type to use on the constructor.
        builder.Register(c => new DemoController(c.Resolve<IRepository<IEntity>>()));

        //We build the container.
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }

autofac の別の方法を使用する別のアプローチがありますが、前の方法は依存関係を自動的に解決するため、十分です。参考までに方法を載せておきます

            builder.RegisterType(typeof(DemoController)).UsingConstructor(typeof(IRepository<IEntity>));

また、サンプル プロジェクトをダウンロードできるリンクを共有し、Autofac がこのマザーでどのように機能するかを非常に明確に示しています。

オートファックT

于 2012-04-27T14:52:58.897 に答える