使用Unity注入构造函数参数值

时间:2017-05-30 15:52:08

标签: .net dependency-injection inversion-of-control unity-container

我正在运行一个MVC应用程序,其中包含许多服务(调用其他服务/帮助程序/等)。我正在尝试使用概述的策略

注入仅在运行时已知的参数值

https://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container

正如文章中提到的那样,最好不要简单地使用Unity作为ServiceLocator - 我也更喜欢而不是来新建一个UnityContainer的实例(而且写得相当丑陋)解析语句)每次我想做任何不寻常的事情(比如注入运行时参数)。

这篇文章现在已经有几年了,Unity现在支持TypeFactory和DelegateFactory类型,所以它可以很容易地进行改进,但是将一个委托注入到构造函数中以获取参数值的想法很好地解耦了这个过程(注意我很乐意讨论同样脱钩的策略,例如抽象到工厂)

我几乎使用文章中描述的委托方法,但是虽然我可以注入委托并让委托调出来获取抽象类中的值,但该类的实例与我放置值的地方,因此委托调用看到的值为null

我尝试过使用命名注册,并尝试了不同的生命周期选项无济于事 - 通常它没有什么区别或Unity没有提取分辨率我得到了...确保有无参数构造函数...异常消息。另请注意,如果我没有分配和检索参数的标记,请随时发表评论

我的代码的本质如下

自举:

container.RegisterType<IExportDetail, ExportDetail>();
container.RegisterType<IExportHelper, ExportHelper>();

container.RegisterType<Func<IExportDetail>>(
    new InjectionFactory(c =>
    //new Func<string, IExportDetail>(name => c.Resolve<IExportDetail>(name))));
    new Func<IExportDetail>(() => container.Resolve<IExportDetail>())));

抽象参数声明:

public interface IExportDetail
{
    string Parm1{ get; set; }
    string Parm2{ get; set; }
}
public class ExportDetail : IExportDetail
{
    public string Parm1{ get; set; }
    public string Parm2{ get; set; }
}

正在呼叫帮助者/服务:

public class ExportHelper : IExportHelper
{
    private IExportDetail _service;
    public ExportHelper(
            Func<IExportDetail> serviceFactory
        )
    {
        _service = serviceFactory();
        _parm1 = _service.Parm1; // <--!!this is null!!
        _parm2 = _service.Parm2; // <--!!this is null!!
    }
}

来电者:

IExportHelper _exportHelper; //<--DI'd
IExportDetail _exportDetail; //<--DI'd

_exportDetail.Parm1 = parm1ValueSetAtRuntime;
_exportDetail.Parm2 = parm2ValueSetAtRuntime;
return _exportHelper;

1 个答案:

答案 0 :(得分:0)

您可以在运行时注册一些类型实例,请参阅下面的示例。

顺便说一句,你想要使用Unity注册某个数据对象的实例并将其放入helpers \ services中,这很奇怪,请参阅NightOwl888的注释。 (我不知道如何回答评论)

自举:

container.RegisterType<Func<string, IExportDetail>>(
    new InjectionFactory(c =>
    new Func<string, IExportDetail>(name => c.Resolve<IExportDetail>(name))));

在运行时注册对象:   

container.RegisterInstance<IExportDetail>("someName", new ExportDetail
{
    Param1 = parm1ValueSetAtRuntime,
    Param2 = parm2ValueSetAtRuntime
});

助手:   

public ExportHelper(Func<string, IExportDetail> serviceFactory)
{
    IExportDetail exportDetail = serviceFactory("someName");
    // Use here exportDetail
}