2010-09-06 75 views
2

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

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' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TFooType' in the generic type or method 'FooFactory.CreateFoo()'

有什么办法来解决这个问题?

我也试过:

Activator.CreateInstance<TFooResult>(); 

这在运行时引发了同样的错误。

+0

奇怪的是我不明白你的代码的任何错误在.NET 4不知道这个限制已经放宽?这是编译时还是运行时错误? – 2010-09-06 10:34:53

+0

啊,我正在运行.NET 3.5。我会做一些挖掘。这是编译时错误。 – 2010-09-06 10:35:55

+0

在这种情况下,请参阅我的答案。 – 2010-09-06 10:46:59

回答

4

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

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

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

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

+0

我试过了 - 同样的错误只是在运行时抛出,而不是在编译时抛出。 – 2010-09-06 10:34:07

+0

@David Neale:调用'nonPublic'重载将处理该问题。更新。 – Ani 2010-09-06 10:36:17

+0

优秀 - 我没有看到超载。谢谢。 – 2010-09-06 10:41:27

0

The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last.

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

是的,谢谢。我意识到这一点.....“有什么办法可以解决这个问题吗?” – 2010-09-06 10:32:32

0

以下几种解决方法可能不多,但我不认为你想这样做!厂内

  • 认沽switch语句,将创建type类型参数的基础 实例。

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

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

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