1
public class TheController : Controller 
{ 
    IThe the; 
    public TheController(IThe the) 
    { 
     //when User.IsInRole("r1") The1 should be injected else r2 
     this.the = the; 
    } 
} 

public class The1 : IThe{} 
public class The2 : IThe{} 

//anybody knows a good way of doing this ? 

回答

2

IHandlerSelector是要走的路。有關使用示例,請參閱this post

或者,如果你喜歡AutoFac般的體驗,您可以使用廠家爲:

container.Register(Component.For<IThe>().UsingFactoryMethod(
    c => HttpContext.Current.User.IsInRole("r1") ? 
    c.Resolve<IThe>("r1") : 
    c.Resolve<IThe>("r2")); 

或者,如果你想只在一個方面IThe具體使用時,可以使用DynamicParameters:

container.Register(Component.For<TheFactory>().Lifestyle.Transient.DynamicParameters(
    (c, d) => HttpContext.Current.User.IsInRole("r1") ? 
    d["the"] = c.Resolve<IThe>("r1") : 
    c.Resolve<IThe>("r2")); 

但是最正確的正確這樣做的方式是IHandlerSelector

1

在Autofac:

var builder = new ContainerBuilder(); 

// Give the different implementations names 
builder.RegisterType<The1>.Named<IThe>("r1"); 
builder.RegisterType<The2>.Named<IThe>("r2"); 

// Use a function for the default IThe 
builder.Register(
    c => HttpContext.Current.User.IsInRole("r1") ? 
    c.Resolve<IThe>("r1") : 
    c.Resolve<IThe>("r2")) 
    .As<IThe>() 
    .ExternallyOwned(); 

如果你有很多角色,你可以使用的方法,而不是內置表達式,如:

builder.Register(c => ChooseTheImplementation(c)) 

(順便說一句,在「ExternallyOwned」修飾符告訴容器函數的結果放置在別處,例如通過具體組件。通常你可以離開它,但它是一個很好的文件:))

+0

據我瞭解這個答案,你可以在應用程序根目錄中執行此註冊。那時,'User'不可用(它是Controller類的一個屬性)。 – 2010-03-26 05:50:50

+0

固定 - 現在使用HttpContext。謝謝馬克。 – 2010-03-26 10:06:10

+0

是溫莎城堡能做這種東西嗎? – Omu 2010-03-26 19:10:02

1

container-agnostic做法顯然採用了Abstract Factory

public interface ITheFactory 
{ 
    IThe Create(IPrincipal user); 
} 

您可以採取ITheFactory的依賴,而不是i將的:

public class TheController : Controller 
{ 
    private readonly IThe the; 

    public TheController(ITheFactory theFactory) 
    { 
     if (theFactory == null) 
     { 
      throw new ArgumentNullException("theFactory"); 
     } 

     this.the = theFactory.Create(this.User); 
    } 
} 

我真的不記得this.User這個時候是否被填充,但如果不是,你可以保留對工廠的引用,並在第一次請求時懶散地解析你的依賴。

但是,Controller.User有點特別,因爲它也應該可以作爲Thread.CurrentPrincipal。這意味着在這種特殊情況下您實際上並不需要引入抽象工廠。取而代之的是,你可以寫一個Decorator執行的每一個選擇它的使用時間:

public class UserSelectingThe : IThe 
{ 
    private readonly IThe the1; 
    private readonly IThe the2; 

    public UserSelectingThe(IThe the1, IThe the2) 
    { 
     if (the1 == null) 
     { 
      throw new ArgumentNullException("the1"); 
     } 
     if (the2 == null) 
     { 
      throw new ArgumentNullException("the2"); 
     } 

     this.the1 = the1; 
     this.the2 = the2; 
    } 

    // Assuming IThe defines the Foo method: 
    public Baz Foo(string bar) 
    { 
     if (Thread.CurrentPrincipal.IsInRole("r1")) 
     { 
      return this.the1.Foo(bar); 
     } 

     return this.the2.Foo(bar); 
    } 
} 

在這種情況下,你將能夠使用原來的TheController類不變。