我正在一家工厂根据两个标准创建具体实例: 1)该类必须从特定的抽象类继承 2)类必须在重写属性中具有特定值 我的代码看起来像这样: public abstract class CommandBase{ public abstract string
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); } } }
我收到错误:
更简洁的方法是定义自己的属性来存储前缀.{System.Reflection.TargetException: Object does not match target type. at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
[AttributeUsage(AttributeTargets.Class)] public class CommandAttribute : Attribute { public String Prefix { get; set; } public CommandAttribute(string commandPrefix) { Prefix = commandPrefix; } }
然后像这样使用它们:
[CommandAttribute("P")] public class PaintCommand : CommandBase {} [CommandAttribute("W")] public class WalkCommand : CommandBase {}
反思:
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); }