【问题标题】:Possible to compile-time check constructor parameters for generic factory function?可以编译时检查通用工厂函数的构造函数参数吗?
【发布时间】:2013-06-16 19:10:52
【问题描述】:

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

Buildit 函数只需要泛型类型和参数列表(在创建具体类时,这些参数用作 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");

    }
}

【问题讨论】:

    标签: c# generics reflection compile-time


    【解决方案1】:

    并非如此,因为您使用的是一种运行时技术的反射...编译器意识到无法创建您的实例的唯一方法是运行您的代码...至少在 CAAS 显示之前起来。

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

    ArgumentException 类几乎就是为这种情况而构建的......如果事情没有按预期工作,则抛出它。

    【讨论】:

    • 我不确定你所说的强制新约束是什么意思。 BuildIt 已经限制在 new() 上。相反,映射到属性也不错,但我更喜欢使用构造函数来保证填充某些字段。 IoC 容器框架会有同样的限制吗?感谢您的意见。
    • 没有 IoC 框架 - IoC 是一种模式/实践。有一些 DI 框架可以帮助 IoC,例如 Microsoft 的 Unity……但是它们也是运行时技术(这是它们的主要功能 - 延迟执行/决定哪个类要解析到运行时)……它们也有同样的问题:如果构造函数参数不匹配,它们会在运行时而不是编译时间。
    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 2013-09-29
    相关资源
    最近更新 更多