2010-08-02 79 views
3

我正在一个客户端(Silverlight)的webmethod集合接口上工作。我试图避免为每个webmethod编写任何自定义代码。所以我创建了一个ServiceCall<TResult>来处理每个调用,TResult指定了服务的返回类型(我用XmlSerializer来创建返回的实例)。客户类公开了一个匹配每个webmethod的函数,该函数所要做的就是创建一个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),但这对我来说并不是什么大问题。惹恼我的是,如果你从外面看我的Client,你只会看到对Ninject的依赖。你不知道,直到你运行尝试进行调用,客户端需要一个实现注册与Ninject的ServiceCall工作。
但是,如果客户构造函数采用了Factory>类型的参数,那么它会更清晰。

在任何情况下,我会认为这将是一个普遍的问题,所以要么有一个共同的解决方案,或它不是一个普遍的问题,我试图做一些愚蠢的事情) 我仍然没有进入依赖注入,所以很可能是这种情况。

+0

是“IServiceCall”特定服务调用的例子(如“富”),或者是这个API你正在建设一个实际的接口? – 2010-08-02 17:34:37

+0

这是一个界面。我的具体实现是ServiceCall。我用它来依赖于一个接口而不是特定的实现。 但这个问题并没有问题。我将编辑帖子。 – 2010-08-02 20:01:21

回答

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

所以,如果我理解你的权利,你有一个类看起来有点像这样:

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是如何工作的,以及它如何让你在工厂通过。

+0

由于篇幅有点短暂,我会在问题中留言。 – 2010-08-02 20:22:10