繁体   English   中英

你是如何制作通用通用工厂的?

[英]How do you make a Generic Generic Factory?

我正在开发一个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构造函数采用了Factory>类型的参数,那么它会更加清晰。

在任何情况下,我认为这将是一个常见的问题,所以要么有一个共同的解决方案,或者它不是一个常见的问题,我试图做一些愚蠢的事情;)我仍然不是那种依赖注入,所以这可能非常情况就是这样。

这是你在寻找什么: 通用工厂模式

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);
        }
    }
}

所以,如果我理解你的话,你会有一个看起来像这样的课:

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如何工作以及它如何让你进入工厂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM