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

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

问题描述

我的问题如下:

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

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)

所有派生类都满足与基类的is-a"关系.

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

代码如下:

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();线.由于该类是抽象类,因此您无法创建它的实例.

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.

如何在不必为每个派生类型对 case 进行硬编码的情况下解决此问题?

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

推荐答案

您可以使 createNewInstanceStep1 通用.我还将 Step2 修改为 void 类型(我希望它修改当前实例,因此返回始终是 return this; 无论如何),因为否则我想在这里使用它的方式真的没有意义.如果像这样改变它没有意义,那么我只使这个方法通用的整个方法将不起作用.

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.

并且 createNewInstance 现在使用反射来调用等效的 return createNewInstanceStep1();.

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天全站免登陆