簡體   English   中英

通過登錄的用戶角色注入不同的實現

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM