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

时间:2010-09-06 10:25:38

标签: 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() {
        return new TFooResult();
    }
}

FooFactoryFoo位于同一个程序集中。类调用工厂方法如下:

var foo = FooFactory.CreateFoo<Foo>();

他们得到编译时错误:

  

'Foo'必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法'FooFactory.CreateFoo()'

中将其用作参数'TFooType'

有没有办法解决这个问题?

我也尝试过:

Activator.CreateInstance<TFooResult>(); 

这会在运行时引发相同的错误。

4 个答案:

答案 0 :(得分:4)

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

//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 

虽然客户也可以这样做。但是,这很容易出现运行时错误。

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

答案 1 :(得分:0)

  

type参数必须有    public 无参数构造函数。与其他人一起使用时   约束,new()约束必须   最后指定。

http://msdn.microsoft.com/en-us/library/d5x73970.aspx

编辑:所以不,如果使用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();
        }

答案 2 :(得分:0)

下面的解决办法很少,但我认为你不想这样做!

  • 将switch语句放在Factory中 这将创建基于实例 关于类型参数的类型。

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

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

答案 3 :(得分:0)

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