我正在开发一个webmethod集合的客户端(Silverlight)接口。我试图避免为每个web方法编写任何自定义代码。所以我创建了一个ServiceCall<TResult>
来处理每个调用,TResult
指定服务的返回类型(我使用XmlSerializer
来创建返回的实例)。客户端类公开了与每个web方法匹配的函数,该函数所要做的就是创建ServiceCall<TResult>
的新实例,并将TResult
指定为方法的预期返回类型。
这很好用。
我也在使用Ninject(依赖注入器)来尝试保持一切独立。 Ninject支持开放式泛型,这对我的ServiceCall<TResult>
非常有用。
但这也意味着我正在注入对Ninject容器的引用。这隐藏了对绑定到容器的ServiceCall<TResult>
的依赖。所以我想注入一个工厂来创建我的ServiceCall<TResult>
实例。这并不棘手,但我想把它变成一个通用的通用工厂。这意味着我希望有Factory<T<>>
这样的方法public T<TU> Createinstance<TU>()
。
但是我不知道如何创建一个类型参数的泛型类,它本身就是一个开放的genric。
.Net中的事件是否可行? - 或者我是否必须创建特定的ServiceCallFactory?
修改 我正在使用依赖关系的接口,但是没有必要将它们混合到这里的问题中,所以我编辑了这个问题。
回应Timwi:
使用依赖注入(DI)的常用方法是将接口绑定到您的实现,只有容器知道这些绑定。然后,您将对代码进行编码。这带来了许多优点。比我在这里提到的更多。
无论如何,它还排除了静态类(因为那将是对特定类的依赖)。相反,我将指示容器(在这种情况下为Ninject)始终为工厂界面提供相同的实例,例如行为。
这排除了public static class Factory<T>
选项,因为它是静态的,如果它不是静态的,我现在需要使用每种类型的T,这有点挫败了使用泛型类的目的。
建议使用具有“完全通用”方法的非泛型类(如我在ServiceCall<MyResult>
而不是MyResult
中传递),这或多或少是我现在所做的(减去静态类部分)。 Ninject容器有一个Get方法,就像你的第二个建议一样
这个问题有两部分;首先它使我的代码直接依赖于一个容器(Ninject),但这对我来说并不是那么大的问题。令我恼火的是,如果你从外面看我的客户,你只会看到对Ninject的依赖。你不会知道,直到你运行尝试打电话,客户需要在Ninject注册的ServiceCall的实现工作。
但是如果Client contructor采用了Factory&gt;类型的参数,那么它会更加清晰。
无论如何,我认为这将是一个常见的问题,所以要么有一个共同的解决方案,要么它不是一个常见的问题,我试图做一些愚蠢的事情;) 我仍然没有进入依赖注入,所以很可能就是这种情况。
答案 0 :(得分:4)
这是你在找什么:Generic Factory Pattern
namespace GenericFactoryPatternTestApp
{
public class Factory< T >
{
private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >();
public Factory()
{
Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes();
foreach (Type type in types)
{
if (!typeof (T).IsAssignableFrom(type) || type == typeof (T))
{
// Incorrect type
continue;
}
// Add the type
_factoryDictionary.Add(type.Name, type);
}
}
public T Create< V >(params object[] args)
{
return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args);
}
}
}
答案 1 :(得分:1)
所以,如果我理解你的话,你会有一个看起来像这样的课程:
public static class Factory<T<>>
{
public static T<TU> CreateInstance<TU>() { /* ... */ }
}
然后你会怎么称呼它?喜欢这个?
var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>();
是什么阻止你简单地宣布像这样的工厂......
public static class Factory<T>
{
public static T CreateInstance() { /* ... */ }
}
......或者......
public static class Factory
{
public static T CreateInstance<T>() { /* ... */ }
}
...然后像这样生成你的实例?
var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance();
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>();
我很抱歉,如果我愚蠢,但我可能需要知道Ninject如何工作以及它如何让你进入工厂。