在构造函数中使用带有不同参数的反射来调用类方法?

时间:2017-03-30 16:14:22

标签: c# reflection constructor

你好我对c#反射很新,我有以下问题。

我有一个CommandDispatcher类,它调用某个可以执行某些操作的Command类。

现在我使用一个开关来确定要调用的命令。

我希望通过使用反射调用正确的命令来简化代码并完全摆脱开关。

但是每个命令在其构造函数中都需要一个或多个服务。我不想改变这一部分。我明白,如果我没有在构造函数中传递任何服务,代码就能正常工作。

因此,当每个命令采用一个或多个服务时,如何使用反射调用我的命令。

以下图片是为了更好地理解:The code with color indicators

我没有注释掉开关,以便于阅读。

以下是pastebin中的代码:https://pastebin.com/AMQeh1zw

我的搜索没有找到任何解决我问题的方法。

2 个答案:

答案 0 :(得分:1)

处理用例的最佳方法是使用IoC和DI。

对于现在的反射情况,您可以使用以下代码确定给定类型的构造函数参数及其类型。

假设有一个班级MyClass

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

您可以使用以下逻辑

获取有关MyClass的所有构造函数的信息
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));
}

现在,一旦您知道构造函数参数的类型,就可以创建这些类型的对象,并为其指定值,并使用它们创建MyClass对象,如下所示。

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());

您会注意到,此处的限制是,您无法设置obj的属性或值,因为它是tyoe object。如果您将其转换为特定类型,那么您最终会获得switch caseif-else阶梯。因此,只要您的类的构造函数需要引用类型(类类型)的参数,此代码就可以正常工作。

答案 1 :(得分:0)

我建议使用依赖注入库,例如Ninjectnuget link。 对于你的purporse,你可以使用下一个结构:

此代码初始化您的依赖注入核心

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

你的开关:

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;
    }