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 ?
答案 0 :(得分: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 :(得分: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”修饰符告诉容器函数的结果被放置在其他地方,例如通过具体的组件。你通常可以把它放在外面,但它可以提供良好的文档:))
答案 2 :(得分:1)
container-agnostic方法显然使用了Abstract Factory:
public interface ITheFactory
{
IThe Create(IPrincipal user);
}
您可以依赖ITheFactory而不是IThe:
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
有点特殊,因为它也应该以{{1}}的形式提供。这意味着在这种特殊情况下你实际上不必引入抽象工厂。相反,您可以编写一个Decorator,每次使用时都会执行选择:
Thread.CurrentPrincipal
在这种情况下,您可以使用原始的TheController类。