0

我正在运行包含多个服务(调用其他服务/帮助程序/等)的MVC应用程序。我试图注入正在使用概述使用Unity注入构造函数参数值

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

正如文章最好是不能简单地用统一的服务定位中提到的策略在运行时才知道的参数值 - 以及,我会更喜欢而不是在每次我想做任何不寻常的事情(比如注入运行时参数)时,都会创建一个UnityContainer实例(并写入相当丑陋的Resolve语句)。

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

我几乎在那里用文章中介绍的委托方法,但是,虽然我可以注入委托并获取委托来调出来获取在抽象类中的值,该类的实例与放置值的实例不同,因此委托调用看到的值为空

我试过使用命名注册,并尝试不同的生命周期选项无济于事 - 通常它没有什么区别,或者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

我认为你的主要问题是你试图注入的是* n ot服务*,它是一个*数据容器*。服务通常*不包含任何状态* - 它们包含要执行的业务逻辑(并且可以传递一个模型,比如'ExportDetail',它不需要接口)。请参阅[本文](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=97)以了解新变量(您应该只使用new关键字)和注射剂之间的区别。 – NightOwl888

+0

Thanks NightOwl - 我在你的文章中阅读文章 - 我可以看到,我的DTO(ExportDetail)不需要通过Unty实例化,因为它只是一个DTO。然而,对于我的要求,它创建的唯一原因是注入 - 如果有更好的方法,它可以很容易地被驳回 - 例如,如果它可以被ExportHelper的工厂取代,那么作为一种策略,我很乐意与 - 我问的问题是如何做到这一点 – TerrorBight

+0

我在互联网上看到了很多例子 - 它们分为三类 - (a)服务定位器(b)它们通过服务代码中的Unity容器注册/解析(c)使用委托或工厂来注入并集中注册Unity中的所有Register Unity代码 - 我的偏好是(c) - 但正如我原始文章中的文章,它实际上并没有显示如何/在哪里实际分配运行时间值 – TerrorBight

回答

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 
} 
+0

感谢乔治 - 这几乎是我已经作为妥协 - 我真的想摆脱编码服务代码中的容器注册语句,每次我想注入构造函数运行时参数(根据原始文章链接中概述的设计)Unity具有集中Bootstrap中所有必需逻辑的功能 – TerrorBight

相关问题