Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用内部构造函数创建泛型类_C#_Factory Pattern_Generics_Object Construction - Fatal编程技术网

C# 使用内部构造函数创建泛型类

C# 使用内部构造函数创建泛型类,c#,factory-pattern,generics,object-construction,C#,Factory Pattern,Generics,Object Construction,是否可以在泛型方法中构造具有内部构造函数的对象 public abstract class FooBase { } public class Foo : FooBase { internal Foo() { } } public static class FooFactory { public static TFooResult CreateFoo<TFooResult>() where TFooResult : FooBase, new() {

是否可以在泛型方法中构造具有内部构造函数的对象

public abstract class FooBase { }

public class Foo : FooBase {
   internal Foo() { }
}

public static class FooFactory {
    public static TFooResult CreateFoo<TFooResult>()
    where TFooResult : FooBase, new() {
        return new TFooResult();
    }
}
它们会得到编译时错误:

“Foo”必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法“foofacture.CreateFoo()”中将其用作参数“TFooType”

有没有办法绕过这个问题

我还尝试:

Activator.CreateInstance<TFooResult>(); 
Activator.CreateInstance();
这会在运行时引发相同的错误

类型参数必须具有 公共无参数构造函数。当与其他设备一起使用时 约束,新的()约束必须 最后指定

编辑:所以不,如果使用new()约束,就不能传递该类,如果不使用new()约束,就可以尝试使用反射来创建新实例

public static TFooResult CreateFoo<TFooResult>()
where TFooResult : FooBase//, new()
        {
            return (TFooResult)typeof(TFooResult).GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] {}, null).Invoke(new object[]{});
            //return new TFooResult();
        }
publicstatictfooresult CreateFoo()
其中TFooResult:FooBase/,new()
{
return(TFooResult)typeof(TFooResult).GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,null,新类型[]{},null).Invoke(新对象[]{});
//返回新的TFooResult();
}

您可以删除
new()
约束并返回:

//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 
尽管客户也可以这样做。然而,这很容易出现运行时错误


这是一个很难以安全的方式解决的问题,因为该语言不允许使用抽象构造函数声明。

下面的解决方法很少,但我认为您不想这样做

  • 将switch语句放入工厂 这将创建基于实例的 关于类型参数的类型

  • FooBase的每个具体实现都将向FooFactory注册,并通过工厂方法自行创建。所以FooFactory将使用内部字典

  • 除了类型参数和具体实现之间的映射之外,在类似的行上扩展将是外部代码(xml文件、配置等)。IOC/DI容器在这里也有帮助

公共类通用工厂
{
公共静态T创建(对象[]参数)
{
变量类型=新类型[args.Length];
对于(变量i=0;i
我试过了-同样的错误只是在运行时而不是在编译时抛出的。@David Neale:调用
非公共的
重载将处理这个问题。更新。太好了-我没有看到过载。谢谢。奇怪的是,我在.NET4中没有发现你的代码有任何错误。不确定这一限制是否已经放宽?这是编译时错误还是运行时错误?啊,我正在运行.NET3.5。我要挖一些。这是一个编译时错误。在这种情况下,请参阅我的答案。
//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 
public class GenericFactory
{
    public static T Create<T>(object[] args)
    {
        var types = new Type[args.Length];
        for (var i = 0; i < args.Length; i++)
            types[i] = args[i].GetType();

        return (T)typeof(T).GetConstructor(types).Invoke(args);
    }
}