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类不变。