2017-06-06 27 views
0

我想註冊通用存儲庫以使用基於實體自定義屬性的特定上下文。下面是我有在Autofac的WithParameter中獲取關閉的實現類型

Globax.asax

//data layer 
foreach (var database in DatabaseManager.Databases) 
{ 
    builder.Register<IDbContext>(c => new CodesObjectContext(database.ConnectionString)) 
     .As<IDbContext>() 
     .Named<IDbContext>(database.Alias) 
     .InstancePerLifetimeScope(); 
} 

builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)) 
    .WithParameter(new ResolvedParameter(
     (pi, ctx) => pi.ParameterType == typeof(IDbContext), 
     (pi, ctx) => ctx.ResolveNamed<IDbContext>((
      { Generic Type Of EfRepository}.GetType() 
       .GetCustomAttributes(typeof(DatabaseAttribute), true)[0] 
        as DatabaseAttribute).Name))) 
    .InstancePerLifetimeScope(); 

我似乎無法到達這裏,{ Generic Type Of EfRepository }。我有可能獲得當前註冊的泛型類型的EfRepository嗎?

+0

「EfRepository 」的每個已關閉版本都將具有相同的「DatabaseAttribute」,因此對於每個「IRepository 」的已關閉版本,它總是會產生相同的「Name」。所以我不認爲你想要做什麼會起作用。 – Steven

+0

我的評論不太關於這個話題。 'DbContext'應該在短時間內使用:創建它,使用它,調用'SaveChanges',並且處理它。在存儲庫的構造函數中傳遞DbContextFactory。 [詳細](http://mehdi.me/ambient-dbcontext-in-ef6/)。 –

回答

0

我設法使用來自ParameterInfo的信息來解決它。這裏是我的解決方案:

//data layer 
      foreach (var database in DatabaseManager.Databases) 
      { 
       builder.Register<IDbContext>(c => new CodesObjectContext(database.ConnectionString)) 
        .As<IDbContext>() 
        .Named<IDbContext>(database.Alias) 
        .InstancePerLifetimeScope(); 
      } 

     builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)) 
      .WithParameter(new ResolvedParameter(
        (pi, ctx) => pi.ParameterType == typeof(IDbContext), 
        (pi, ctx) => ctx.ResolveNamed<IDbContext>(
         (pi.Member.DeclaringType.GetGenericArguments()[0] //get generic type 
         .GetCustomAttributes(typeof(DatabaseAttribute), true)[0] as DatabaseAttribute).Name))) //get attribute database name 
     .InstancePerLifetimeScope(); 
1

您可以訪問的參數信息

builder.RegisterGeneric(typeof(EfRepository<>)) 
     .As(typeof(IRepository<>)) 
     .WithParameter(new ResolvedParameter(
       (pi, c) => pi.ParameterType == typeof(IDbContext), 
       (pi, c) => c.ResolveNamed<IDbContext>(
        pi.Member.DeclaringType 
        .GetGenericArguments()[0] 
        .GetCustomAttributes(typeof(DatabaseAttribute), true) 
        .OfType<DatabaseAttribute>() 
        .First() 
        .Name))) 
     .InstancePerLifetimeScope(); 

另一個解決方案是使用OnPreparing僞事件,並注入新的Parameter

的​​具體解析式利用
builder.RegisterGeneric(typeof(EfRepository<>)) 
     .As(typeof(IRepository<>)) 
     .OnPreparing(e => { 
      e.Parameters = e.Parameters.Union(
       new[] { 
        new ResolvedParameter(
         (pi, c) => pi.ParameterType == typeof(IDbContext), 
         (pi, c) => { 
          String databaseName = 
           pi.Member 
           .DeclaringType 
           .GetGenericArguments()[0]    
           .GetCustomAttributes(typeof(DatabaseAttribute), true) 
           .OfType<DatabaseAttribute>() 
           .FirstOrDefault() 
           .?Name 
          if (String.IsNullOrEmpty(databaseName) 
          { 
           // TODO 
          } 

          c.ResolveNamed<IDbContext>(databaseName) 
         } 
        ) 
       }); 
     }) 
     .InstancePerLifetimeScope(); 

您還可以在自定義Module上創建添加OnPreparing事件。有關更多信息,請參閱http://docs.autofac.org/en/latest/examples/log4net.html