1

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

4

2 Answers 2

2

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
    }
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for taking time into it, I am looking into your solution trying to make it fit to the working example..
May I ask, how do I set a value for a known Property of class1 in the last box of code? Like class1.MyKnownProperty = 123; ?
I got Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference' inside the task, after declaring dynamic instance (in the Console.WriteLine). Any advice please?
Fixed it, thank you very much. Only small thing now is how to make it lookup in multiple namespaces, unfortunately I have mane (instead of just the $"NetCoreScripts.{className}" for example). Thank you very much for your contribution, appreciated.
@Nick You are welcome, about list all classes in a namespace, this answer may help you stackoverflow.com/a/949285/3789481
0

The problem that you are trying to solve is with regard Creation of new objects. Here are some common coding patterns used for the same.

I would say this is a good use case for Factory pattern. What we do is delegate the responsibility for creating objects to a factory.

Firstly, we can identify them as classes that extend an abstract class

public abstract class MehodResponseBase {
    public abstract void  DoSpecialThing();
    public abstract string responseText;
}

public class Method100Response201 : MehodResponseBase
{
    public override responseText = "Method100Response201";
    public string R1_01 { get; set; }
    public override void DoSpecialThing()
    { Console.WriteLine ("Something Blue..}"); }
}
public class Method100Response404 : MehodResponseBase
{
    public override responseText = "Method100Response404";

    public string R2_01 { get; set; }
    public override void DoSpecialThing()
    { Console.WriteLine ("Something Old..}"); }
}
public class Method110Response200 : MehodResponseBase
{
    public override responseText = "Method110Response200";

    public string R3_01 { get; set; }
    public override void DoSpecialThing()
    { Console.WriteLine ("Something New..}"); }
}

Then we can extract their creation into a factory

pubic class MethodResponseFactory() 
{
    public static MehodResponseBase Make(int method, int response)
    {
        if (method == 100) 
        {
            if(response == 201) 
            {
                return new Method100Response201();
            }

            if(response == 404) 
            {
                return new Method100Response404();
            }
        }

        if (method == 110) 
        {
            if (response == 200) 
            {
                return new Method110Response200();
            }
        }

        throw new MethodResponseCreationException($"Cannot create for mothod: {method} and response: {response}")
    }

}

So your response model is refactored to

public static string ResponseModel(int method, int response)
{
        try 
        {
            return MethodResponseFactory.Make(method, response).returnClass;
        }
        catch (MethodResponseCreationException ex)
        {
            return string.Empty;
        }
}

So, as you can see, all the delegation for creating the object is now in the factory. And resonseModel class simply calls the factory to build a class based on the method and response.

1 Comment

Thank you very much for your answer, I appreciate, but I was looking forward for a solution with Activator (reason is I have many classes and not too many common point - although they have some - to create abstraction), sorry if the example oversimplified it..

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.