你好我对c#反射很新,我有以下问题。
我有一个CommandDispatcher类,它调用某个可以执行某些操作的Command类。
现在我使用一个开关来确定要调用的命令。
我希望通过使用反射调用正确的命令来简化代码并完全摆脱开关。
但是每个命令在其构造函数中都需要一个或多个服务。我不想改变这一部分。我明白,如果我没有在构造函数中传递任何服务,代码就能正常工作。
因此,当每个命令采用一个或多个服务时,如何使用反射调用我的命令。
以下图片是为了更好地理解:The code with color indicators
我没有注释掉开关,以便于阅读。
以下是pastebin中的代码:https://pastebin.com/AMQeh1zw
我的搜索没有找到任何解决我问题的方法。
答案 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 case
或if-else
阶梯。因此,只要您的类的构造函数需要引用类型(类类型)的参数,此代码就可以正常工作。
答案 1 :(得分:0)
我建议使用依赖注入库,例如Ninject和
nuget 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;
}