4

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

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 三种不同的报告文档类型。我有一个通用的处理IReportHandler<T>程序(与上面的相同),这个处理程序提供了处理报告文档的所有功能。例如

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

现在我想使用像 Unity(或其他一些框架)这样的框架进行依赖注入,以通过配置决定我是要使用 CrystalReportingservices还是 List 和 Label。

当我指定我的映射时,我可以注入我的ChrystalReportHandler,但我怎样才能在左侧注入 T 或者更好的词 The Type of ReportDocument

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

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

4

3 回答 3

2

我认为,在您当前的设计中,您正在IDocumentHandler与特定 Document ( ReportDocumentor MediaDocument) 之间创建“依赖关系”,因此如果您想IDocumentHandler<ReportDocument or MediaDocument>直接在代码中使用,您必须假设您的容器会为您提供这一点。在这种情况下,容器不应该负责解析文档类型。

你会考虑像这样改变你的设计吗?

public interface IDocumentHandler
{
    IDocument Document { get; set; }

    void Load(IDocument doc);

    void Load(string PathToDoc);

    void Execute();

    void Execute(IDocument doc);

}

public class IDocument { }
public class ReportDocument : IDocument { }
public class MediaDocument : IDocument { }
public class FinanceDocumentProcessor : IDocumentHandler { }
public class MarketingDocumentProcessor : IDocumentHandler { }
于 2008-12-10T10:20:02.277 回答
1

如果我理解正确,你有两个选择。

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

    container.AddComponent>(typeof(FooHandler));

  2. 如果你有一个类 DocHandler 你可以使用开放的泛型类型注册组件

    container.AddComponent(typeof(IDocHandler<>), typeof(DocHandler<>));

那么每次你解析 IDocHandler 时,你都会得到一个 DocHandler 实例,当你解析 IDocHandler 时,你会得到 DocHandler

希望有帮助

于 2008-12-22T22:27:02.440 回答
1

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

尝试:

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

这将创建两个接口。将所有通用的、非 T 特定的东西放入基本接口中,并将其他所有东西放入通用接口中。

由于您想要将对象解析为的代码,您不知道处理器的类型,因此无论如何您都不能在那里调用任何特定于 T 的代码,因此您不会通过使用非- 通用接口。


编辑:我注意到我的回答被否决了。如果人们对事情投反对票会留下评论他们为什么这样做,那就太好了。我不在乎声誉点,此时这只是轻微的噪音,但如果答案有严重错误,那么我想知道以便我可以删除答案(如果它偏离目标) 或更正。

现在,在这种情况下,我怀疑要么是最初的被提问者投了反对票,因此要么没有发布足够的信息,所以他实际上是在问他所问的以外的东西,或者他不太明白我的回答,哪个是可以理解的,因为它有点短,或者不理解它的人再次出于同样的原因否决了它。

现在,详细说明。

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

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

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

这是不可能的。

因此我的回答。

于 2008-12-10T09:39:10.847 回答