我正在一家工厂根据两个标准创建具体实例:
1)该类必须从特定的抽象类继承
2)类必须在重写属性中具有特定值
我的代码看起来像这样:
public abstract class CommandBase
{
public abstract string Prefix { get; }
}
public class PaintCommand : CommandBase
{
public override string Prefix { get; } = "P";
}
public class WalkCommand : CommandBase
{
public override string Prefix { get; } = "W";
}
class Program
{
static void Main(string[] args)
{
var paintCommand = GetInstance("P");
var walkCommand = GetInstance("W");
Console.ReadKey();
}
static CommandBase GetInstance(string prefix)
{
try
{
var currentAssembly = Assembly.GetExecutingAssembly();
var concreteType = currentAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(CommandBase)) &&
!t.IsAbstract &&
t.GetProperty("Prefix").GetValue(t).ToString() == prefix).SingleOrDefault();
if (concreteType == null)
throw new InvalidCastException($"No concrete type found for command: {prefix}");
return (CommandBase)Activator.CreateInstance(concreteType);
}
catch (Exception ex)
{
return default(CommandBase);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:
{System.Reflection.TargetException:Object与目标类型不匹配.在System.Reflection.RuntimeMethodInfo.CheckConsistency(目标对象)的System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck在System.Reflection.RuntimeMethodInfo.Invoke(对象OBJ(对象OBJ,的BindingFlags invokeAttr,粘结剂粘结剂,对象[]参数,CultureInfo的培养物), BindingFlags invokeAttr,Binder binder,Object []参数,CultureInfo文化)
更简洁的方法是定义自己的属性来存储前缀.
[AttributeUsage(AttributeTargets.Class)]
public class CommandAttribute : Attribute
{
public String Prefix { get; set; }
public CommandAttribute(string commandPrefix)
{
Prefix = commandPrefix;
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它们:
[CommandAttribute("P")]
public class PaintCommand : CommandBase
{}
[CommandAttribute("W")]
public class WalkCommand : CommandBase
{}
Run Code Online (Sandbox Code Playgroud)
反思:
static CommandBase GetInstance(string prefix)
{
var currentAssembly = Assembly.GetExecutingAssembly();
var concreteType = currentAssembly.GetTypes().Where(commandClass => commandClass.IsDefined(typeof(CommandAttribute), false) && commandClass.GetCustomAttribute<CommandAttribute>().Prefix == prefix).FirstOrDefault();
if (concreteType == null)
throw new InvalidCastException($"No concrete type found for command: {prefix}");
return (CommandBase)Activator.CreateInstance(concreteType);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
89 次 |
| 最近记录: |