我的问题如下:
我有一个需要抽象的基类。它具有几个派生类,每个派生类都有其自己的特殊属性,这些属性包含在Properties成员中。
我需要能够创建这些派生类之一的新实例,以便所有成员都是等效的,但是修改新实例不会修改原始实例。
最后,我想这样做而不必在基类的每个派生类型中进行硬编码。 (诚然,这将是最简单的解决方案,但这不是重点)
所有派生类都与基类满足“is-a”关系。
这是代码:
public abstract class BaseClass
{
//Default properties here
int x, y, z, ...;
//Custom made class to hold custom properties
protected Attributes Properties;
public BaseClass createNewInstance()
{
return createNewInstanceStep1();
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract BaseClass createNewInstanceStep2();
protected BaseClass createNewInstanceStep1()
{
BaseClass newInstance = new BaseClass(); // <- Doesn't work because class is abstract
//Copy default properties
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;
//Call the new instance's step 2 method, and return the result.
return newInstance.createNewInstanceStep2();
}
}
此代码的问题是BaseClass newKeyFrame = new BaseClass();线。由于该类是抽象类,因此无法创建它的实例。
问题在于,我需要能够调用派生类的任何类型的构造函数,因为它们在构造函数中都具有不同的代码,这些代码无法共享。
我听说使用Reflection可能是一个可行的解决方案,但是我不知道该怎么做。
如何解决此问题而不必为每种派生类型都进行硬编码?
最佳答案
您可以将createNewInstanceStep1
设为通用。我还已经将Step2
修改为void
类型(我希望它可以修改当前实例,因此无论如何,返回值始终是return this;
),因为否则,这实际上对我想使用的方式没有意义在这里。如果像这样更改它没有意义,那么我仅使该方法通用的整个方法将行不通。
现在createNewInstance
使用反射来调用return createNewInstanceStep1<this.GetType()>();
的等效项。
public BaseClass createNewInstance()
{
var method = typeof(BaseClass).GetMethod("createNewInstanceStep1", BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(this.GetType());
var value = method.Invoke(this, null);
return (BaseClass)value;
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract void createNewInstanceStep2();
protected T createNewInstanceStep1<T>() where T : BaseClass, new()
{
T newInstance = new T(); // works!
//Copy default properties
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;
//Call the new instance's step 2 method, and return the result.
newInstance.createNewInstanceStep2();
return newInstance;
}
如果这行不通,则另一种方法是self-referential generic type。最好避免这种情况,因为这会造成困惑,并且总体上不是一个好的设计。
public sealed class SubClass : BaseClass<SubClass>
{
protected override SubClass createNewInstanceStep2()
{
Console.WriteLine("In step 2");
return this;
}
}
public abstract class BaseClass<T> where T : BaseClass<T>, new()
public T createNewInstance()
{
return createNewInstanceStep1();
}
//Each derived class implements their own version of this,
//to handle copying any custom members contained in Properties.
protected abstract T createNewInstanceStep2();
protected T createNewInstanceStep1()
{
T newInstance = new T();
...
关于c# - 通过基类创建派生类的实例,而无需进行硬编码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19692348/