创建带有内部构造函数的通用类

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

FooFactoryFoo 在同一个程序集中。类可以按如下方式调用工厂方法:

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

他们遇到了编译时错误:

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

有没有什么办法可以解决这个问题?

我也尝试过:

Activator.CreateInstance<TFooResult>(); 

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


奇怪的是,在.NET 4中使用您的代码时,我没有收到任何错误信息。不确定这个限制是否已经放宽了?这是编译时还是运行时错误? - Paul Ruane
啊,我正在运行.NET 3.5。我会进行一些挖掘。这是一个编译时错误。 - David Neale
在这种情况下,请看我的答案。 - Paul Ruane
4个回答

5
您可以移除new()限制并返回:
//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true); 

虽然客户端也可以这样做,但这种方法容易出现运行时错误。

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


我试过了,相同的错误只是在运行时抛出而不是编译时。 - David Neale
@David Neale:调用nonPublic重载将处理此问题。已更新。 - Ani
太好了 - 我没有看到那个重载。谢谢。 - David Neale

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

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

0

以下有一些解决方法,但我不认为你想走这条路!

  • 在工厂内部放置切换语句 根据类型参数创建实例。

  • 每个 FooBase 的具体实现将使用工厂方法向 FooFactory 注册。因此,FooFactory 将使用内部字典。

  • 扩展类似的行,除了类型参数和具体实现之间的映射外,还可以是外部代码(xml 文件、配置等)。IOC/DI 容器也可用于此处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接