简体   繁体   中英

Dynamically convert Base Class to Derived Class

For People that don't like to read a lot of Pseudo-Code:

I want to dynamically convert a base class to a derived class based on a variable and then use this newly converted derived class without having to do heavy casting. Is this even possible and if so how can i accomplish it?

What I'm trying to do in Pseudo-Code:

I have a basic architecture that goes like this:

// Base Class:

class BaseClass
{
    public BaseClass(string data)
    {
        Data = data;
    }

    public string Data { get; set; }
}

// Interface for derived Classes:

interface IStuff
{
    void DoStuff();
}

// Derived Classes: 
// (Don't have own Properties besides the ones they get from BaseClass and 
// no other Methods than they have to implement from IStuff)

class DerivedClass1 : BaseClass, IStuff
{
    public void DoStuff()
    {
        Console.WriteLine($"1: {Data}");
    }
}

class DerivedClass2 : BaseClass, IStuff
{
    public void DoStuff()
    {
        Console.WriteLine($"2: {Data}");
    }
}

Now the tricky part: I want to be able to do something like this:

UnknownType GetDerivedClass(BaseClass baseClass, int value)
{
    switch(value)
    {
        case 1:
        return baseClass as DerivedClass1;
        case 2:
        return baseClass as DerivedClass2;
        default:
        return null;
    }
}

var value = 1;
var baseClass = new BaseClass("data here");

var derivedClass = GetDerivedClass(baseClass, value);

derivedClass.DoStuff(); // prints "1: data here"

In this scenario if i would change the 'value' variable to 2 it would print "2: data here". Is this possible somehow without casting yourself to death or do you have another architectural choice that would make what i'm trying to do a lot easier?

  using System;
  namespace ConsoleApp2
  {
  class Program
  {
    static void Main(string[] args)
    {
        IStuff IStuff = new DerivedClass1("data1 here");
        IStuff.DoStuff(); // prints "1: data here"

        IStuff = new DerivedClass2("data2 here");
        IStuff.DoStuff(); // prints "1: data here"

        Console.ReadKey();
    }

    public class BaseClass
    {
        public BaseClass(string data)
        {
            Data = data;
        }

        public string Data { get; set; }
    }

    // Interface for derived Classes:

    public interface IStuff
    {
        void DoStuff();
    }

    // Derived Classes: 
    // (Don't have own Properties besides the ones they get from BaseClass and 
    // no other Methods than they have to implement from IStuff)

    public class DerivedClass1 : BaseClass, IStuff
    {
        public DerivedClass1(string data) : base(data)
        {

        }
        public void DoStuff()
        {
            Console.WriteLine($"1: {Data}");
        }
    }

    public class DerivedClass2 : BaseClass, IStuff
    {
        public DerivedClass2(string data) : base(data)
        {

        }
        public void DoStuff()
        {
            Console.WriteLine($"2: {Data}");
        }
    }


    //UnknownType GetDerivedClass(BaseClass baseClass, int value)
    //{
    //    switch (value)
    //    {
    //        case 1:
    //            return baseClass as DerivedClass1;
    //        case 2:
    //            return baseClass as DerivedClass2;
    //        default:
    //            return null;
    //    }
    //}

    //var value = 1;

}
}

It is like you want to instantiate a derived class based on your url or whatever information you know at compile time (because you are using a switch case block and returning class based on known values).

You can use a dictionary in your base class. For example :

Dictionary<int,Func<BaseClass>> DerivedClasses ={
    [1] = ()=> new DerivedClass1(),
    [2]= () => new DerivedClass2()
    };

Of course, you encapsulate the behavior you want in each derived class.

Now GetDerivedType(int value) should be in BaseClass and will just return

if (DerivedClasses.TryGetValue(value, out var derivedClass))
    return derivedClass;

return null;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM