关于c#:动态实例化类

Dynamically instantiate class

我试图动态地实例化抽象类的类后代,但是激活器强迫我重写每个后代的构造函数。有没有办法避免这种情况?

P.S:我需要在构造函数中传递参数,只有在那里它才能被写,否则,它将永远被读取!


Is there a way to avoid this?

short answer:yes,当您在派生类中定义no构造函数时,将使用(抽象)基类构造函数。定义一个构造函数时,必须重新定义所有的构造函数。不是没有变通模式。

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

如何实现目标,

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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 {
}

用法(dotnetfidle):

1
2
3
4
5
6
7
8
public class Program
{
    public void Main()
    {
        Duck d =  Duck.Create<Donald>("Hello  World");
        Console.WriteLine(d.DucksParam0);
    }
}


构造函数不是继承的,因此如果必须用这些参数通过构造函数实例化子对象,那么需要在基本上执行base(p1, p2, ..., pn)的子类中编写一个新的构造函数。

查看您的代码,您的构造函数似乎只分配/初始化字段,所以没有理由不能在构造函数之外的某个地方这样做,只要您适当地控制它。这可能是一个长期的尝试,但我觉得这更像是你想要的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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实例化对象,因为默认的构造函数受到保护。此外,根据您的注释,请注意,属性的定义是为了只有您可以设置值,这是您在显式忽略setter时在代码中所做的操作。