简体   繁体   中英

Invoke Class Method using Reflection with different params in constructor?

Hello i am very new to c# reflection and i have the following problem.

I have a CommandDispatcher class that invokes a certain Command class that does something.

For now i use a switch to determinate what command to invoke.

i wanted to simplify the code by using reflection to invoke the right command and get rid of the switch for good.

But each command takes a certain service or more in its constructor. I don't want to change that part . I understand that if i had no services passed in the constructor the code would work fine.

So how can i invoke my commands with reflection when each command takes one or many services.

Here is an image for better understanding: The code with color indicators

I left the switch not commented out for easier reading.

Here is the code in pastebin: https://pastebin.com/AMQeh1zw

My search did not result in finding anything to solve my problem.

The best way to handle your use case is to use IoC and DI.

For the case of reflection as of now you can determine the constructor parameters and their types for a given type by using following code.

Let say there is a class MyClass

public class MyClass
{
     int age;
     double salary;
     public MyClass(int x, double y)
     {
         age = x;
         salary = y;
     }
}

You can get information about all the constructors of MyClass using following logic

var ctors = typeof(MyClass).GetConstructors();
// assuming class MyClass has only one constructor
var ctor = ctors[0];
foreach (var param in ctor.GetParameters())
{
    Console.WriteLine(string.Format(
        "Param {0} is named {1} and is of type {2}",
        param.Position, param.Name, param.ParameterType));
}

Now once you know the type of the constructor parameters you can create objects of those types with values assigned to them and use them to create object of MyClass as following.

var parameters = new List<object>();
foreach (var param in ctor.GetParameters())
{
    var obj = Activator.CreateInstance(param.ParameterType);
    parameters.Add(obj);
}

var myClassObj = Activator.CreateInstance(typeof(MyClass), parameters.ToArray());

The limitation here, you would notice, is you can not set properties or values of obj as it is of tyoe object . If you convert it to specific type then you will end up having switch case or if-else ladder. So as long as the constructor of your class expects parameters of reference type (class type) this code would work fine.

I suggest to use Dependency Injection library for example Ninject and nuget link . For your purporse you can use next construction:

This code init your Dependency Injection core

    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

And your switch:

switch (commandName)
        {
            case "RegisterUser":
                RegisterUserCommand registerUser = kernel.Get<RegisterUserCommand>();
                result = registerUser.Execute(commandParameters);
                break;
            case "Login":
                LoginCommand loginCommand = kernel.Get<LoginCommand>();
                result = loginCommand.Execute(commandParameters);
                break;
    }

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