我正在实现Command
设计模式的变体。我有一个带有一些子类的抽象CodedCommand
类,每个子类都有一个类型为char
的覆盖“Code”属性。然后,每个子类都有责任“封装”与其关联的自己的Code
字母。
用例是:当某些串行解析器接收到char / byte时,我想创建相应子类的实例,以进一步处理命令有效负载。
我的问题是:我不知道如何从每个子类中获取特定值。
我目前的实施情况如下。用注释突出显示的问题是type.GetProperty("Code")
返回null!
internal abstract class CodedCommand
{
internal abstract char Code { get; }
}
internal class EventA : CodedCommand
{
internal override char Code => 'A';
}
internal class EventB : CodedCommand
{
internal override char Code => 'B';
}
public class CommandCreator
{
Dictionary<char, Type> _typeMap
= new Dictionary<char, Type>();
public CommandCreator()
{
var types = GetType().Assembly.GetTypes()
.Where(type => type.IsSubclassOf(typeof(CodedCommand)))
.Where(type => !type.IsAbstract);
foreach (var type in types)
{
var field = type.GetProperty("Code"); // returns null!!!
var value = field.GetValue(null);
var code = (char)value;
_typeMap[code] = type;
}
}
CodedCommand BuildCommand(char code)
{
_typeMap.TryGetValue(code, out Type type);
if (type != null)
{
return (CodedCommand)(Activator.CreateInstance(type));
}
return null;
}
}
所以我的问题是如何解决这个问题?
答案 0 :(得分:3)
以下是获取财产价值的完整解决方案:
var types = GetType().Assembly.GetTypes()
.Where(type => type.IsSubclassOf(typeof(CodedCommand)) && !type.IsAbstract);
foreach (var type in types)
{
var obj = Activator.CreateInstance(type);
var field = type.GetProperty("Code", BindingFlags.Instance | BindingFlags.NonPublic);
var value = field.GetValue(obj);
var code = (char)value;
_typeMap[code] = type;
}
请注意field.GetValue
需要对象实例才能工作,NonPublic
- 获取内部属性的PropertyInformation时需要BindingFlag。
答案 1 :(得分:1)
问题是您的属性标记为internal
,而不是public
,我们无法使用您正在使用的重载访问非公共属性。
如果您想要flags
以外的其他属性,则需要使用this overload指定public
参数:
type.GetProperty("Code",BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public)
搜索具有指定名称的公共属性。
GetProperty(string name,BindingFlags bindingAttr)
overload:
使用指定的绑定约束搜索指定的属性。