4

是否可以在泛型方法中使用其内部构造函数构造对象?

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

FooFactory与 位于同一程序集中Foo。类调用工厂方法是这样的:

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

他们得到编译时错误:

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

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

我也试过:

Activator.CreateInstance<TFooResult>(); 

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

4

4 回答 4

5

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

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

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

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

于 2010-09-06T10:33:28.333 回答
0

类型参数必须有一个 公共的无参数构造函数。当与其他约束一起使用时,必须最后指定 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();
        }
于 2010-09-06T10:29:03.693 回答
0

可能有以下几种解决方法,但我认为您不想那样做!

  • 将 switch 语句放入 Factory 中,该语句将根据类型参数的类型创建实例。

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

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

于 2010-09-06T10:43:41.530 回答
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);
    }
}
于 2011-03-02T14:22:54.903 回答