通过基类创建派生类的实例而不用硬编码 [英] Creating an instance of derived class through the base class without hardcoding

查看:139
本文介绍了通过基类创建派生类的实例而不用硬编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题如下:



我有一个基类需要抽象。它有几个派生类,每个都有自己的特殊属性包含在Properties成员中。



我需要能够创建一个新的实例类,所以所有的成员是等价的,但是修改新的实例不会修改原来的。



最后,我想做,而不必硬编码在每个派生基类的类型。



所有的派生类都满足与基类的is-a关系(这是不可否认的,但是这不是最简单的解决方案) 。



这是代码:

  public abstract class BaseClass 
{
//默认属性
int x,y,z,...;

//自定义类保存自定义属性
protected属性;

public BaseClass createNewInstance()
{
return createNewInstanceStep1();
}

//每个派生类实现它们自己的版本,
//来处理包含在属性中的任何自定义成员。
protected abstract BaseClass createNewInstanceStep2();

protected BaseClass createNewInstanceStep1()
{
BaseClass newInstance = new BaseClass(); //< - 不工作,因为类是抽象的

//复制默认属性
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;

//调用新实例的步骤2方法,并返回结果。
return newInstance.createNewInstanceStep2();
}
}

此代码的问题是BaseClass newKeyFrame = new BaseClass();线。因为类是抽象的,你不能创建它的实例。



问题是,我需要能够调用任何类型的构造函数的派生类,因为他们都有不同的代码在他们的构造函数,不能共享。



我听说使用Reflection可能是一个可行的解决方案,但我不知道如何。 / p>

如何解决这个问题,而不必在每个派生类型的情况下硬编码?

解决方案

您可以使 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;
}

//每个派生类实现它们自己的版本,
//来处理包含在属性中的任何自定义成员。
protected abstract void createNewInstanceStep2();

protected T createNewInstanceStep1< T>()其中T:BaseClass,new()
{
T newInstance = new T // works!

//复制默认属性
newInstance.x = x;
newInstance.y = y;
newInstance.z = z;

//调用新实例的步骤2方法,并返回结果。
newInstance.createNewInstanceStep2();
return newInstance;
}



如果这不起作用,另一种方法是自引用通用类型

  public sealed class SubClass:BaseClass< SubClass> ; 
{
protected override SubClass createNewInstanceStep2()
{
Console.WriteLine(In step 2);
return this;
}
}
public abstract class BaseClass< T>其中T:BaseClass< T>,new()
public T createNewInstance()
{
return createNewInstanceStep1();
}

//每个派生类实现它们自己的版本,
//来处理包含在属性中的任何自定义成员。
protected abstract T createNewInstanceStep2();

protected T createNewInstanceStep1()
{
T newInstance = new T();
...


My problem is as follows:

I have a base class that needs to be abstract. It has several derived classes, each with their own special properties that are contained in the Properties member.

I need to be able to create a new instance of one of these derived classes, so that all the members are equivalent but modifying the new instance doesn't modify the original.

Finally, I want to do it without having to hardcode in every derived type of the base class. (Which would, admittedly, be the easiest solution, however that isn't the point)

All the derived classes satisfy an "is-a" relationship to the base class.

Here is the code:

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();
    }
}

The issue with this code is the BaseClass newKeyFrame = new BaseClass(); line. As the class is abstract, you cannot create an instance of it.

The problem is that I need to be able to call the constructor of whatever type the derived class is, as they all have different code in their constructors that cannot be shared.

I've heard that using Reflection might be a viable solution, however I have no idea how.

How can I solve this without having to hardcode in a case for every derived type?

解决方案

You could make createNewInstanceStep1 generic. I've also modified the Step2 to be type void (I'm expecting it to modify the current instance, so the return would always be return this; anyway), because otherwise it doesn't really make sense the way I'd like to use it here. If it doesn't make sense to change it like this, then my whole approach of only making this method generic won't work.

And createNewInstance now uses reflection to call the equivalent of 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;
}

If this won't work, another approach is a self-referential generic type. It's good to avoid this, though, because it's confusing and overall not a good design.

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();
        ...

这篇关于通过基类创建派生类的实例而不用硬编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆