2011-12-20 102 views
4

我使用Autofac作爲我的IoC容器。 我有:如何註冊開放泛型類型,封閉泛型類型並使用autofac裝飾兩者?

  1. IRepository<>,我的存儲庫接口;
  2. DbContextRepository<>,使用EntityFramework的DbContext存儲庫的通用實現;
  3. 裝配中的一些封閉類型庫,如PersonRepository : DbContextRepository<Person>;
  4. RepositoryDecorator<>,它用一些標準的額外行爲來裝飾我的存儲庫;

我使用autofac登記他們都像這樣:

builder.RegisterGeneric(typeof(DbContextRepository<>)) 
      .Named("repo", typeof(IRepository<>)); 

builder.RegisterGenericDecorator(
       typeof(RepositoryDecorator<>), 
       typeof(IRepository<>), 
       fromKey: "repo");    

var repositorios = Assembly.GetAssembly(typeof(PersonRepository)); 
builder.RegisterAssemblyTypes(repositorios).Where(t => t.Name.EndsWith("Repository")) 
      .AsClosedTypesOf(typeof(IRepository<>)) 
      .Named("repo2", typeof(IRepository<>)) 
      .PropertiesAutowired(); 

builder.RegisterGenericDecorator(
       typeof(RepositoryDecorator<>), 
       typeof(IRepository<>), 
       fromKey: "repo2"); 

我所試圖做的是:

  1. 註冊DbContextRepository<>爲通用實現的IRepository<>;
  2. 然後註冊關閉的類型存儲庫,以便它們可以在需要時重載以前的註冊;
  3. 然後裝飾它們,當我要求容器解析一個IRepository時,它給了我一個RepositoryDe​​corator,它具有正確的IRepository實現,它是一個DbContextRepository或者已經註冊的封閉類型。

當我嘗試解析沒有封閉類型實現的IRepository<Product>時,它將返回Correcly Decorated DbContextRepository。

但是,當我嘗試解決一個IRepository<Person>,這具有封閉式的實現,這也給了我一個裝飾DbContextRepository,而不是裝飾PersonRepository。

+0

我試圖複製你的問題,你可以提供更多的代碼,具體的裝飾器可能有幫助嗎? RepositorioVisibilidade的意思是RepositoryDe​​corator嗎? – 2011-12-20 14:21:51

+0

感謝您的更正。 – rcaval 2011-12-21 12:34:56

+0

我會嘗試進行一些單元測試,並將它作爲擴展名添加到Autofac中,並將信用分配給@ default.kramer,類似於'.AsNamedClosedTypesOf(...)' – rcaval 2011-12-21 12:52:52

回答

6

問題是Named("repo2", typeof(IRepository<>))沒有做你的想法。您需要爲正在掃描的類型明確指定類型。

static Type GetIRepositoryType(Type type) 
{ 
    return type.GetInterfaces() 
     .Where(i => i.IsGenericType 
      && i.GetGenericTypeDefinition() == typeof(IRepository<>)) 
     .Single(); 
} 

builder.RegisterAssemblyTypes(this.GetType().Assembly) 
    .Where(t => t.IsClosedTypeOf(typeof(DbContextRepository<>))) 
    .As(t => new Autofac.Core.KeyedService("repo2", GetIRepositoryType(t))) 
    .PropertiesAutowired(); 
+0

它工作正常。我在找的東西就像.AsClosedTypesOf(typeof(IRepository <>),withName:「repo」),它不存在,但正是你所做的。 – rcaval 2011-12-21 12:37:01

+0

很棒的回答。這是一個棘手的問題,因爲它不能從API中發現。 – 2015-07-02 11:40:04

+0

謝謝!不太可能發現, - 非常好,不要誤解我的意思 - 文檔只顯示通用註冊器頂層的通用裝飾器示例 – 2015-07-24 07:54:09