C# 是否可以编译时检查通用工厂函数的构造函数参数?

C# 是否可以编译时检查通用工厂函数的构造函数参数?,c#,generics,reflection,compile-time,C#,Generics,Reflection,Compile Time,我正在试验一些工厂类型代码,其中BuildIt函数返回一个仅基于传入的泛型类型的具体类型。泛型类型被限制为BaseAbstract类的后代 Buildit函数只需要泛型类型,然后是参数列表(在创建具体类时,这些参数在Buildit函数中用作构造函数参数) 下面的示例代码按预期工作(先打印“A”然后打印“B”) 但如果我试着打电话给这样的人,问题就会出现: var b = fs.BuildIt<B>("B", "C"); var b=fs.BuildIt(“b”、“C

我正在试验一些工厂类型代码,其中BuildIt函数返回一个仅基于传入的泛型类型的具体类型。泛型类型被限制为BaseAbstract类的后代

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

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

但如果我试着打电话给这样的人,问题就会出现:

        var b = fs.BuildIt<B>("B", "C");
var b=fs.BuildIt(“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");

    }
}
公共抽象类BaseAbstract
{
公共字符串名称=”;
公共重写字符串ToString()
{
返回名称;
}
}
公开A类:基本抽象类
{
公共A()
{
Name=“A”;
}
}
公共类B:基本抽象类
{
公共图书馆B()
{
}
公共B(字符串参数)
{
Name=param;
}
}
公营工厂
{
public T BuildIt(params object[]args),其中T:BaseAbstract,new()
{
tx=(T)Activator.CreateInstance(typeof(T),args);
返回x;
}
}
公共类主类
{
公共静态void Main(字符串[]args)
{
//这些很好
工厂fs=新工厂();
var a=fs.BuildIt();
var b=fs.BuildIt(“b”);
Console.WriteLine(a);
控制台写入线(b);
//由于“C”参数,这将导致运行时错误
//var b2=fs.BuildIt(“B”、“C”);
}
}

不太可能,因为您使用的是反射,这是一种运行时技术。。。编译器意识到无法创建实例的唯一方法是运行代码。。。至少在CAA出现之前

一种方法可能是采用不同的方法:在方法中对泛型类型强制一个新的()约束(确保所有类型都有一个无参数构造函数),然后将构造函数参数映射为属性,而不是映射到类型上?如果您想要不变性,可能并不理想,但反射可以写入私有类型等


这几乎就是类构建的场景。。。如果东西不能按预期工作,就扔掉它。

我不知道你说的强制新约束是什么意思。BuildIt已对new()进行了约束。相反,映射到属性并不坏,但我更喜欢使用构造函数作为填充某些字段的保证。IoC容器框架会有同样的限制吗?感谢您的投入。没有IoC框架——IoC是一种模式/实践。有一些DI框架可以帮助IoC,比如微软的Unity。。。不过,它们也是运行时技术(这是它们的主要特性—将哪个类的执行/决策延迟到运行时)。。。它们也有同样的问题:如果构造函数参数不匹配,它们会在运行时呕吐,而不是在编译时呕吐。