[英]inject different implementations by logged User Role
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 ?
IHandlerSelector
是必經之路。 有關用法的示例,請參見此帖子 。
另外,如果您喜歡類似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
在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”修飾符告訴容器該函數的結果已放置在其他位置,例如通過具體組件。您通常可以省略它,但可以提供很好的文檔:))
容器不可知論的方法顯然使用了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
有點特殊,因為它也應該作為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類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.