Поменять базовый класс во время выполнения? - PullRequest
0 голосов
/ 21 апреля 2020

Я знаю, что его очень долго спрашивали go, но ответы не были действительно полезны, C# сильно изменился с тех пор, и моя проблема немного другая.

Я в среде, которая позволяет настраивать загрузку DLL, чтобы люди могли добавлять свой контент в работающую программу, скажем, в субмодули, но, конечно, это обходится некоторыми ограничениями.

(отредактировано в примере)

Пример, ни один из этого кода не существует

Public abstract class Car
{
    int tires=4;
    string color;

    public Car(string c){
        color = c;
    }
}

public class SportCar : Car{
    int doors = 3;
    int maxspeed=100;

    public void changeSpeed(int i){
        maxspeed = i;
    }
}

public class Ferrari : Car{
    string model = "Ferrari";
}

Что я хочу получить после этого -

public ClassResult{
    int tires=4;
    string color;
    int doors = 3;
    int maxspeed=100;
    string model = "Ferrari";

    public ClassResult(string c){
        color = c;
    }
    public void changeSpeed(int i){
        maxspeed = i;
    }
}

Поэтому я попросил указать причину наследования, как показано, что проблема решена очень легко если у вас есть контроль над кодом и можете переписать его. Но я не. Единственное, что я могу сделать, это постобработать его, чтобы получить конечный результат.

Таким образом, изменение во время выполнения родительского класса Ferrari или SportCar в примере решило бы это, так как это было бы наследство classi c но это может быть другой путь. В настоящее время я решаю эту проблему, отбрасывая один из дочерних классов, но это не совсем удовлетворительно и может привести к другим проблемам.

Какой точный контроль у меня есть, это класс над всеми теми, которые содержат коллекция добавленных классов. И я называю некоторые методы внутри них, которые они все должны реализовать. (Вот почему они все наследуют один и тот же базовый класс)

Надеюсь, так будет понятнее.

1 Ответ

0 голосов
/ 21 апреля 2020

Я бы посоветовал смотреть в направлении композиции вместо наследования.

Исходя из вашего примера кода, я бы предложил следующую композицию: (PS. Это просто псевдокод, чтобы понять смысл для композиции я набрал его здесь, возможно, есть некоторые ошибки сборки: p)

public class Car
{
    public List<CarModule> Modules;

    public InvokeMethod(string methodName)
    {
        Module moduleWithMethod = Modules.FirstOrDefault(m => m.HasMethod(methodName));

        moduleWithMethod.InvokeModuleMethod(methodName);
    }
}

public abstract class CarModule
{
    protected abstract Dictionary<string,Action> _moduleMethods;

    public bool HasMethod(string methodName) => _moduleMethods.Keys.Contains(methodName);

    public void InvokeModuleMethod(string methodName)
    {
        _moduleAction[methodName].Invoke()
    }
}

public sealed CarMovement : CarModule
{
    int _speed = 5;
    const int _maxSpeed = 100;

    private Dictionary<string,Action> _moduleMethods = 
    {
        ["ToMaxSpeed"] = () => ToMaxSpeed()
    }

    private void ToMaxSpeed()
    {
        _speed = maxSpeed;
    }
}

public class Test
{
    public void TestCase()
    {
        var speedingCar = new Car();
        speedingCar.Modules.Add(new CarMovement());

        speedingCar.InvokeMethod("ToMaxSpeed");
    }
}

Конечно, я бы не предложил использовать тип Action в качестве значения для словаря, а вместо этого использовать шаблон команды для инкапсуляции поведения. Или что-то типа того. Но, надеюсь, это куда-то вас приведет

...