2016-12-14 65 views
2

我有兩個不同的服務(實體框架上下文),我注入都在我的應用程序並註冊爲以下幾點:指定要Autofac其命名服務來解決

builder.Register<WriteContext>().Named("Write"); 
builder.Register<ReadContext>().Named("Read"); 

現在,我有兩個不同的命令處理程序(我有兩個以上),每一個被注入了DbContext如下:

public class CommandAHandler : ICommandHandler { 

    private readonly DbContext context; 
    // this handler should get "Write" context 
    public CommandAHandler(DbContext context) { 
     this.context = context; 
    } 

} 

public class CommandBHandler : ICommandHandler { 

    private readonly DbContext context; 
    // this handler should get "Read" context 
    public CommandBHandler(DbContext context) { 
     this.context = context; 
    } 

} 

我怎麼可以指定CommandAHandler拿到類型的「寫」和CommandBHandler一個實例來獲得式「閱讀」的實例?使用,當然,Autofac註冊

+1

如果Autofac行爲像城堡,你會做定義的參數名稱與註冊名稱相同 - 因此它們在註冊和參數中都是「readContext」和「writeContext」。 – stuartd

+0

它確實不是現在,我只是從城堡轉移到Autofac而錯過城堡已經 – Raffaeu

+0

的一些不錯的功能在你的榜樣,你要註冊'WriteContext'和'ReadContext'的類型,但該命令處理程序期待' DbContext'。讓每一個明確它所期望的會是什麼樣的上下文會做到這一點,但也許這只是在你的例子中.. – stuartd

回答

2

您在這裏違反Liskov Substitution Principle(因此SOLID原則)。您有一個「抽象」(即DbContext),但是如果您將只讀版本插入到期望可寫入的消費者中,應用程序將會中斷。這表明您正在違反LSP。

的LSP決定了你必須爲每個情況不同的抽象。這基本上意味着你應該直接注入ReadContext和WriteContext。這將立即解決您的註冊問題,因爲你可以定義你的處理程序爲:

public CommandAHandler(WriteContext context) 
public CommandBHandler(ReadContext context) 

這使您可以簡化您的註冊於以下內容:

builder.Register<WriteContext>(); 
builder.Register<ReadContext>(); 
+0

感謝您指出了這一點 – Raffaeu

1

您可以使用Lambda表達式來處理註冊到510C。例如:

builder.Register(c => new CommandAHandler(c.Resolve<WriteContext>())); 
builder.Register(c => new CommandBHandler(c.Resolve<ReadContext>())); 
0

假設WriteContextReadContext註冊爲DbContext

builder 
    .RegisterType<CommandAHandler>() 
    .WithParameters(
     new[] { 
      new ResolvedParameter(
       (pi, ctx) => pi.ParameterType == typeof(DbContext), 
       (pi, ctx) => ctx.ResolveNamed<DbContext>("Write") 
      ) 
     }); 
builder 
    .RegisterType<CommandBHandler>() 
    .WithParameters(
     new[] { 
      new ResolvedParameter(
       (pi, ctx) => pi.ParameterType == typeof(DbContext), 
       (pi, ctx) => ctx.ResolveNamed<DbContext>("Read") 
      ) 
     });