【问题标题】:Dynamically instantiate class动态实例化类
【发布时间】:2014-01-26 22:43:14
【问题描述】:

我正在尝试动态实例化抽象类的后代类,但激活器迫使我将构造函数覆盖到每个后代。有没有办法避免这种情况?

P.S:我需要在构造函数中传递参数,只有那里可以Write,否则会一直被读取!

【问题讨论】:

  • 你不能重写构造函数......并且不清楚你的StackOverflow在里面......
  • 你不应该在类名前加上I,即使类是抽象的。
  • 为什么你的班级是abstract?从帖子中看不出来。
  • 我来自Delphi编程,也许有另一种方法可以做我想做的事......
  • 你不能只创建一个抽象类的实例。 必须有一个具体的派生类。你有这样的课吗?如果您能提供一个简短但完整的程序来演示问题,那将非常有帮助。

标签: c# instantiation activator


【解决方案1】:

有没有办法避免这种情况?

简短回答:是的,当您在派生类中定义 no 构造函数时,将使用(抽象)基类构造函数。当你定义一个时,你必须重新定义所有的构造函数。
并非没有解决方法。

编辑:对不起,我错了,它只适用于无参数构造函数。

如何实现目标,

正在使用受保护的无参数构造函数和静态 Create 方法:

public abstract class Duck {

    private string _DucksParam0;

    public string DucksParam0 {
        get {
            return  _DucksParam0;
        }
    }

    // Using protected, this constructor can only be used within the class instance
    // or a within a derived class, also in static methods
    protected Duck() { }

    public static DuckT Create<DuckT>(string param0)
        where DuckT : Duck
    {
        // Use the (implicit) parameterless constructor
        DuckT theDuck = (DuckT)Activator.CreateInstance(typeof(DuckT));

        // This is now your "real" constructor
        theDuck._DucksParam0 = param0;

        return theDuck;
    }

}

public class Donald : Duck {
}

用法(dotnetfiddle):

public class Program
{
    public void Main()
    {
        Duck d =  Duck.Create<Donald>("Hello  World");
        Console.WriteLine(d.DucksParam0);
    }
}

【讨论】:

  • 谢谢,这是个好主意,我得重新考虑整个程序。
  • 我和你一样,这就是程序员的生活;)创建一个备份/新分支,重新编写你的基类和所有派生类,然后试一试。
【解决方案2】:

构造函数不是继承的,所以如果你必须通过带有这些参数的构造函数来实例化一个子对象,那么你需要在子类中编写一个新的构造函数,基本上就是base(p1, p2, ..., pn)

查看您的代码,您的构造函数似乎只分配/初始化字段,因此只要您适当地控制它,就没有理由不能在构造函数之外的某个地方执行此操作。这可能是一个长镜头,但我觉得这是你想要的更多:

public abstract class Parent
{
    protected bool foo
    {
        get;
        private set; // just set the property setter as private
    }

    protected Parent() {
        // protected so all instances are created through createAnotherX
        // note that nothing is initialized here!
    }

    public abstract int Enter(); // To override in child classes

    // Option 1: use generics
    public static T createAnother1<T>(bool f) where T : Parent, new()
    {
        T p = new T();
        p.foo = f;

        return p;
    }
    // Option 2: use the runtime type
    public static Parent createAnother2(Type t, bool f)
    {
        Parent p = Activator.CreateInstance(t) as Parent;
        p.foo = f;

        return p;
    }

    // Examples
    public static void Main()
    {
        Parent p1 = Parent.createAnother1<Child>(true);
        Parent p2 = Parent.createAnother2(typeof(Child), true);
    }
}
// the child class only has to worry about overriding Enter()
public class Child : Parent
{
    public override int Enter()
    {
        return 1;
    }
}

请注意,您必须通过createAnotherX 实例化对象,因为默认构造函数是受保护的。此外,根据您的评论,请查看该属性已定义,以便只有您可以设置值,这是您在显式忽略设置器时尝试在代码中执行的操作。

【讨论】:

  • 问题是我需要在构造函数中传递参数,只有那里才可以写,否则只会读!
  • 泛型 T 也不允许我使用重载的构造函数 T(this, Parameters);
  • @MatheusFreitas 查看您的代码,您的构造函数似乎只分配/初始化字段,因此您没有理由不能在 createAnotherX 方法中执行此操作。请注意,您不能只在其他地方实例化这些类,必须通过createAnotherX 完成,因为默认构造函数是受保护的。
  • 好的,我将始终使用静态方法创建一个新的 Parent 实例。这是一个好的设计吗?
  • @MatheusFreitas 不,你不需要,你只需要在 createAnotherX 方法中初始化它们。默认构造函数什么都不做。查看编辑后的答案
猜你喜欢
  • 2019-11-08
  • 2011-11-27
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多