簡體   English   中英

注冊類型時如何將運行時值傳遞給構造函數參數?

[英]How to pass runtime value to constructor parameter when register a type?

背景:

我有很多名為XxxService的類,其中一個構造函數參數是UserId,就像

public XxxService: IXxxService
{
     public XxxService(string userId, IMmmService mmm, INnnService nnn) {....}
}

userId來自HttpContext.Current.Request.Cookies。 服務類的數量很大,所以我不想為每個服務類創建一個IIdProvider接口。

我知道我可以在注冊時將編譯時值傳遞給構造函數。

container.RegisterType<IService, Service>
    (new InjectionConstructor(5,                      //<-- compile time value
             container.Resolve<IMmmService>(), 
             container.Resolve<INnnService>()));

如何將函數傳遞給構造函數? 就像是:

container.RegisterType<IService, Service>
    (new InjectionConstructor( ()=>GetIdFromRequest(),  //<--- runtime value
             container.Resolve<IMmmService>(), 
             container.Resolve<INnnService>() ))

我也知道有一個InjectionFactory

container.RegisterType<IService, Service>
     (new InjectionFactory( 
          (x)=> new Service( 
             GetIdFromRequest(), 
             container.Resolve<IMmmService>(), 
             container.Resolve<INnnService>()))

但這需要手動解決其他參數。

有沒有更好的方法呢? 我只想通過名稱索引將運行時值傳遞給其中一個參數,其他參數應由容器自動處理。

所以我想要的最重要的是:

// fake code
container.RegisterType<IService, Service>
    (new InjectedParameter( 0,       // the first parameter 
             ()=>GetIdFromRequest()  // <--- runtime value
             )

InjectionFactory方法中,使用Resolve方法重載,允許您指定ResolverOverride ,特別是ParameterOverride ,並以這種方式傳遞運行時值。 為了避免StackOverflowException ,您可以使用附加的命名注冊以及為相關參數提供的編譯StackOverflowException ,如下所示:

class A
{
    public A(int id, B b, C c)
    {
        Trace.WriteLine("Got " + id);
    }
}

class B { }

class C { }

static void Main(string[] args)
{
    using (var unity = new UnityContainer())
    {
        unity.RegisterType<A>(
            "compile-time", 
            new InjectionConstructor(-1, 
                new ResolvedParameter<B>(), 
                new ResolvedParameter<C>()
                )
        );
        unity.RegisterType<A>(
            new InjectionFactory(
            u => u.Resolve<A>("compile-time", 
                new ParameterOverride("id", new Random().Next()))
            )
        );
        unity.Resolve<A>();
        unity.Resolve<A>();
        unity.Resolve<A>();
    }
}

我發現您的InjectionFactory方法沒有實際問題。

但是,擁有一個將用戶名作為其狀態的一部分的服務的整個概念對我來說似乎是錯誤的。

但是你最好將用戶參數實現為服務,並注入它,以明確它以這種方式工作,而不是使它成為服務對象生命周期的一部分,如果你在Service類控制器中傳遞一個值,就會發生這種情況。 。

public interface IAuthenticationService
{
    string GetCurrentUserName();
}

public class CookieBasedAuthenticationService : IAuthenticationService
{
 /// ...
}

然后,您可以完全使用InjectionConstructor刪除配置代碼的一部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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