C# 你如何制造一个通用工厂?

C# 你如何制造一个通用工厂?,c#,.net,generics,dependency-injection,ninject,C#,.net,Generics,Dependency Injection,Ninject,我正在开发webmethod集合的客户端(Silverlight)接口。我试图避免为每个webmethod编写任何自定义代码。因此,我创建了一个ServiceCall来处理每个调用,TResult指定服务的返回类型(我使用XmlSerializer来创建返回的实例)。client类公开了一个与每个webmethod匹配的函数,该函数所要做的就是创建一个新的ServiceCall实例,并将TResult指定为该方法的预期返回类型。 这很好用 我还使用(依赖注入器)尝试保持一切独立。Ninject支

我正在开发webmethod集合的客户端(Silverlight)接口。我试图避免为每个webmethod编写任何自定义代码。因此,我创建了一个
ServiceCall
来处理每个调用,
TResult
指定服务的返回类型(我使用
XmlSerializer
来创建返回的实例)。client类公开了一个与每个webmethod匹配的函数,该函数所要做的就是创建一个新的
ServiceCall
实例,并将
TResult
指定为该方法的预期返回类型。 这很好用

我还使用(依赖注入器)尝试保持一切独立。Ninject支持开放泛型,这在my
ServiceCall
中非常有效

但这也意味着我正在注入对Ninject容器的引用。它隐藏了对绑定到容器的
ServiceCall
的依赖关系。因此,我想注入一个工厂来创建我的
ServiceCall
实例。这并不棘手,但我想让它成为一个通用工厂。这意味着我希望有类似于
Factory
的东西,它将有一个方法
public T Createinstance()

但我不知道如何用一个类型参数创建泛型类,它本身就是一个开放的genric

它在.Net中是否可能发生事件还是必须创建特定的ServiceCallFactory

编辑: 我正在为依赖项使用接口,但是没有必要将它们混合到问题中,所以我将其编辑掉了

响应Timwi: 使用依赖项注入(DI)的常见方法是将接口绑定到实现,只有容器知道这些绑定。然后根据接口编写代码。这带来了很多好处。比我在这里能提到的还要多。
无论如何,它也排除了静态类(因为这将是对特定类的依赖)。相反,我将指示容器(在本例中为Ninject)始终以类似于单例的行为为工厂接口提供相同的实例。
这排除了
公共静态类工厂
选项,因为它是静态的,如果它不是静态的,我现在需要使用所有类型的T,这在某种程度上违背了创建泛型类的目的。
建议使用一个带有“完全泛型”方法的非泛型类(比如我传入
ServiceCall
,而不是
MyResult
),这或多或少是我现在正在做的事情(减去静态类部分)。Ninject容器有一个Get方法,它的工作方式与您的第二个建议类似。
这个问题分为两个部分;首先,它使我的代码直接依赖于一个容器(Ninject),但这对我来说并不是什么大问题。让我恼火的是,如果你从外面看我的客户端,你只会看到对Ninject的依赖。在运行“尝试进行呼叫”之前,您不会知道客户端需要在Ninject注册的ServiceCall实现才能工作。
但是,如果客户机构造函数采用类型为Factory>的参数,则会更清楚

在任何情况下,我都会认为这是一个共同的问题,所以要么有一个共同的解决方案,要么这不是一个共同的问题,我正试图做一些愚蠢的事情;)
我仍然不太喜欢依赖项注入,所以情况很可能就是这样。

如果我理解正确的话,您的类看起来有点像这样:

public static class Factory<T<>>
{
    public static T<TU> CreateInstance<TU>() { /* ... */ }
}
公共静态类工厂
{
公共静态T CreateInstance(){/*…*/}
}
然后你会怎么称呼它?像这样

var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>();
var myServiceCall=Factory.CreateInstance();
是什么阻止你像这样简单地宣布工厂

public static class Factory<T>
{
    public static T CreateInstance() { /* ... */ }
}
公共静态类工厂
{
公共静态T CreateInstance(){/*…*/}
}
。。。或者这个

public static class Factory
{
    public static T CreateInstance<T>() { /* ... */ }
}
公共静态类工厂
{
公共静态T CreateInstance(){/*…*/}
}
。。。然后像这样生成实例

var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance();
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>();
var myServiceCall=Factory.CreateInstance();
var myServiceCall=Factory.CreateInstance();

如果我是个哑巴,我很抱歉,但我可能需要知道Ninject是如何工作的,以及它是如何让你通过工厂的。

这就是你想要的:

命名空间GenericFactoryPatternTestApp
{
公共类工厂
{
私有只读字典\u factoryDictionary=新字典();
公共工厂()
{    
Type[]types=Assembly.GetAssembly(typeof(T)).GetTypes();
foreach(类型中的类型)
{
如果(!typeof(T).IsAssignableFrom(type)| | type==typeof(T))
{
//错误类型
继续;
}
//添加类型
_factoryDictionary.Add(type.Name,type);
}
}
公共T创建(参数对象[]参数)
{
return(T)Activator.CreateInstance(_factoryDictionary[typeof(V).Name],args);
}
}
}

“IServiceCall”是一个特定服务调用的示例(如“foo”),还是您正在构建的此API的实际接口?它是一个接口。我的具体实现是ServiceCall。我使用它来依赖于接口,而不是特定的实现。但它可能与这个问题毫无关系。我会编辑这篇文章。我会在问题中留下评论,因为这里的篇幅有点短。
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);
        }
    }
}