可以为通用工厂函数编译时检查构造函数参数吗?

时间:2013-06-20 03:54:47

标签: c# generics reflection compile-time

我正在尝试一些工厂类型代码,其中BuildIt函数仅根据传入的泛型类型返回具体类型。泛型类型仅限于BaseAbstract类的后代。

Buildit函数只需要泛型类型,然后是params列表(在创建具体类时,params在BuildIt函数中用作构造函数参数)。

下面的示例代码按预期工作(打印" A"然后" B")

但如果我尝试调用类似的东西,就会出现问题:

        var b = fs.BuildIt<B>("B", "C");

由于B类没有带2个参数的构造函数,因此在运行时失败。

是否有可能做这样的事情,除非在编译时失败?如果没有,还有另一种方法可以解决这个问题,以便可以进行编译时检查(如果所有这些都必须被抛出并开始完全不同的事情那么无关紧要)

示例代码

public abstract class BaseAbstract
{
    public string Name ="";
    public override string ToString ()
    {
        return Name;
    }
}

public class A : BaseAbstract
{
    public A()
    {
        Name = "A";
    }
}

public class B : BaseAbstract
{
    public B()
    {
    }

    public B(string param)
    {
        Name = param;
    }
}

public class Factory
{
    public T BuildIt<T>(params object[] args) where T : BaseAbstract, new()
    {
        T x = (T)Activator.CreateInstance(typeof(T), args);
        return x;
    }
}

public class MainClass
{
    public static void Main (string[] args)
    {
        //These are fine
        Factory fs = new Factory();
        var a = fs.BuildIt<A>();
        var b = fs.BuildIt<B>("B");
        Console.WriteLine (a);
        Console.WriteLine (b);

          //This would cause runtime error because of the "C" paramter
          //var b2 = fs.BuildIt<B>("B", "C");

    }
}

1 个答案:

答案 0 :(得分:2)

不是真的,因为你正在使用反射这是一种运行时技术......编译器意识到无法创建你的实例的唯一方法就是运行你的代码......至少在CAAS出现了。

一个选项可能是以不同方式处理:在方法中强制对泛型类型使用new()约束(确保所有类型都有无参数构造函数),然后将构造函数参数作为属性映射到您的类型上?如果你想要不变性,也许不理想,但反思可以写入私人类型等等......

这就是为 ArgumentException 类构建的场景......如果内容没有按预期工作,请抛出它。