泛型类型依赖注入:如何注入T

时间:2008-12-10 09:05:46

标签: inversion-of-control c#-2.0 unity-container

我想在我的应用程序中以相同的方式处理不同类型的文档 因此: 我有这样的通用界面。

public interface IDocHandler<T>where T: class
{

T Document { get;set;}

void Load(T doc);

void Load(string PathToDoc);

void Execute();

void Execute(T doc);

}

对于不同类型的文档,我实现了这个接口。

例如:

public class FinanceDocumentProcessor:IDocumentHandler<ReportDocument>
{} 


public class MarketingDocumentProcessor:IDocumentHandler<MediaDocument>
{} 

然后我当然可以这样做:

IDocumentHandler<ReportDocument> docProc= new FinanceDocumentProcessor();

如果我知道如何在运行时注入T以使上面的线路松散耦合,那将是非常令人兴奋的......

IDocumentHandler<ReportDocument> docProc = container.resolve("FinanceDocumentProcessor());

但我想根据配置来决定我想要我的FinanceDomcumentProcessor还是我的MarketingDocumentProcessor ...因此我也必须在左侧网站上注入T ... 由于我必须使用c#2.0,我不能使用魔术这个词“var”,这在这种情况下会有很多帮助...但是我怎样才能将它设计为开放灵活...


对于所有评论的误解和感谢表示歉意,但我还有另一个例子来表示我的挑战(也许我使用了错误的设计)...... 但我试一试:相同的情况,但不同的解释

示例图片我有:

ReportingService,Crystal,ListAndLabel 三种不同的报告文档类型。我有一个通用的Handler IReportHandler<T>(与上面相同),这个Handler提供了处理报告Document的所有功能。 例如

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

现在我想使用类似Unity(或其他框架)的框架来进行依赖注入,以决定是否要使用Crystal,Reportingservices或List和Label。

当我指定我的映射时,我可以注入ChrystalReportHandler但是如何在左侧或更好的单词ReportDocument中注入T。

IReportHandler<T (this needs also to be injected)> = IOContainer.Resolve(MyMappedType here) 

我的问题是左站点,当然因为它与类型耦合但我有我的映射...是否可以基于Mapping生成对象并分配映射类型?或者基本上也在左侧注入T? 或者这种方法不适合这种情况。

3 个答案:

答案 0 :(得分:2)

我认为,根据您当前的设计,您在IDocumentHandler与特定文档(ReportDocumentMediaDocument)之间创建了“依赖关系”,因此如果您想使用{{ 1}}直接在你的代码中你必须假设你的容器会给你这个。在这种情况下,容器不应负责解析文档类型。

你会考虑改变你的设计吗?

IDocumentHandler<ReportDocument or MediaDocument>

答案 1 :(得分:1)

您需要在左侧使用非通用接口。

尝试:

public interface IDocumentHandler { }
public interface IDocumentHandler<T> : IDocumentHandler { }

这将创建两个接口。将所有常见的,非特定于T的特性放入基础界面,以及通用的其他所有内容。

由于你想要解析一个对象的代码,你不知道处理器的类型,你无法在那里调用任何特定于T的代码,所以你不会丢失任何东西使用非通用接口。


修改:我注意到我的答案已被低估了。如果人们贬低事情会留下评论,为什么他们这样做会很好。我不关心声望点,这点只是微小的噪音,但如果答案有严重错误,那么我想知道我可以删除答案(如果它偏离目标)或纠正它。

现在在这种情况下,我怀疑原来的被问者是否已经对它进行了贬低,因此要么没有发布足够的信息,所以他实际上询问的不是他所询问的内容,或者他不太了解我的内容。回答,这是可以理解的,因为它有点短,或者是那个不理解它的人,也是出于同样的原因。

现在,详细说明。

你不能在左侧注射任何东西。那是不可能的。该代码必须编译,正确,并在编译时100%“存在”。对于那部分,你不能说“我们会告诉你T在运行时是什么”。这是不可能的。

所以你唯一留下的就是彻底删除T.使用依赖项的代码完全不依赖于T.或者,至少使用反射来发现T是什么,并根据这些知识做事。

这就是你所能做的一切。根据您从右侧方法返回的内容,您无法使左侧的代码自行更改。

这是不可能的。

因此我的回答。

答案 2 :(得分:1)

如果我理解正确,您有两种选择。

  1. 如果您有实现它的接口IDocHandler和多个类,则必须明确注册每个类型,如下所示:

    container.AddComponent&GT;(typeof运算(FooHandler));

  2. 如果您有一个类DocHandler,则可以使用开放泛型类型

    注册组件

    container.AddComponent(typeof(IDocHandler&lt;&gt;),typeof(DocHandler&lt;&gt;));

  3. 然后每次解析IDocHandler时,您将获得DocHandler的实例,当您解析IDocHandler时,您将获得DocHandler

    希望有所帮助