Search code examples
c#static-methodsactivatordynamicobject

C# Instantiate a Class from String name


Having multiple classes doing many things, I am obliged to instantiate one of them, populate some properties and call a method. A sample would be having the below methods e.g.

        public class Method100Response201
    {
        public string R1_01 { get; set; }
        public void DoSpecialThing()
        { Console.WriteLine ("Something Blue..}"); }
    }
    public class Method100Response404
    {
        public string R2_01 { get; set; }
        public void DoSpecialThing()
        { Console.WriteLine ("Something Old..}"); }
    }
    public class Method110Response200
    {
        public string R3_01 { get; set; }
        public void DoSpecialThing()
        { Console.WriteLine ("Something New..}"); }
    }

all of them inside Program class in the same namespace, where I have the mechanism to find out which Class I need:

       static void Main(string[] args)
    {
        int[] MethodResponse = DoSomethingHere (23, "something", true);
        string DerivedClassName = ResponseModel(MethodResponse[0], MethodResponse[1]);
        Console.WriteLine (
            "For method " + MethodResponse[0].ToString () 
            + " and response " + MethodResponse[1].ToString ()
            + " you must instantiate Class " 
            + DerivedClassName);
        Console.ReadKey ();

        //how do I do this????
        //const string objectToInstantiate = "MyProject.Domain.MyNewTestClass, MyTestProject";
        //var objectType = Type.GetType (objectToInstantiate);
        //dynamic instantiatedObject = Activator.CreateInstance (objectType) as ITestClass;
        // set a property value
        //instantiatedObject.Name = DerivedClassName;
        // get a property value
        //string name = instantiatedObject.Name;

        // call a method - output "Something Blue.."
        //Console.Write (instantiatedObject.DoSpecialThing ());

    }

    public static int[] DoSomethingHere (int param1, string param2, bool whatever)
    {
        int firstInt = 0; int secondInt = 0;
        //
        //lots of work here, I end up with method and selector.. 
        //
        firstInt = 100;
        secondInt = 201;
        return new int[] { firstInt, secondInt };
    }

    public static string ResponseModel(int method, int response)
    {
        string returnClass = String.Empty;

        switch (method)
            {
            case 100:
                if (response == 201)
                { Console.WriteLine ("Case 100,201"); returnClass = "Method100Response201"; }
                else
                { Console.WriteLine ("Case 100,404"); returnClass = "Method100Response404"; }
                break;
            case 110:
                Console.WriteLine ("Case 100,404"); returnClass = "Method110Response200";
                break;
            case 120:
                // ...
                break;
            }
        return returnClass;
    }

I tried with something called Activator, I am no expert and this is really critical for me. Could someone please help me? (I left commented on some code I am trying to, based on published solutions here in SO. Thank you).


Solution

  • This technical called Reflection, that means call an instance from string. My calling class will be

    public class Class1
    {
        public string Property { get; set; } = "I'm class1";
        public void DoSpecialThings()
        {
            Console.WriteLine("Class1 does special things");
        }
    }
    

    Next I create an instance in a static function, should put your all classes in a same namespace to easy control

        public static dynamic GetClassFromString(string className)
        {
            var classAddress = $"NetCoreScripts.{className}";
            Type type = GetType(classAddress);
    
            // Check whether the class is existed?
            if (type == null)
                return null;
    
            // Then create an instance
            object instance = Activator.CreateInstance(type);
    
            return instance;
        }
    

    And a GetType method

        public static Type GetType(string strFullyQualifiedName)
        {
            Type type = Type.GetType(strFullyQualifiedName);
            if (type != null)
                return type;
            foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = asm.GetType(strFullyQualifiedName);
                if (type != null)
                    return type;
            }
            return null;
        }
    

    I use dynamic type to implement quickly, basically you can use interface for explicit coding.

        static async Task Main(string[] args)
        {
            dynamic instance = GetClassFromString("Class1");
    
            Console.WriteLine(instance.GetType().FullName); //NetCoreScripts.Class1
    
            Console.WriteLine(instance.GetType().Name); //Class1
    
            Console.WriteLine(instance.Property); //I'm class1
    
            instance.Property = "Class1 has been changed";
            Console.WriteLine(instance.Property); //Class1 has been changed
    
            instance.DoSpecialThings(); // Class1 does special things
        }