简体   繁体   English

通过Reflection读取子类的非静态属性值

[英]Read non-static property value of a subclass via Reflection

I am implementing a variation of the Command design pattern. 我正在实现Command设计模式的变体。 I have an abstract CodedCommand class with some subclasses, each of one with an overriden "Code" property of type char . 我有一个带有一些子类的抽象CodedCommand类,每个子类都有一个类型为char的覆盖“Code”属性。 Each subclass has then the responsibility to "encapsulate" its own Code letter to which it is associated. 然后,每个子类都有责任“封装”与其关联的自己的Code字母。

The use case is: when some serial parser receive a char/byte, I want to create an instance of the appropriate subclass, to further process the command payload. 用例是:当某个串行解析器接收到char / byte时,我想创建相应子类的实例,以进一步处理命令有效负载。

My problem is: I don't know how to get the specific value from each subclass. 我的问题是:我不知道如何从每个子类获取特定值。

My current implementation is below. 我目前的实施情况如下。 The problem, highlighted with a comment, is that type.GetProperty("Code") is returning null! 用注释突出显示的问题是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;
    }
}

So my question is how can I fix this design? 所以我的问题是如何修复这个设计?

Here is complete solution for getting value of property: 这是获得财产价值的完整解决方案:

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

Please note that field.GetValue needs object instance to work and NonPublic -BindingFlag is needed when getting PropertyInformation for internal property. 请注意, field.GetValue需要对象实例才能工作,并且在获取内部属性的PropertyInformation时需要NonPublic -BindingFlag。

The problem is your property is marked as internal , not public and we cannot access the non-public properties using the overload which you are using. 问题是您的属性被标记为internal ,而不是public ,我们无法使用您正在使用的重载访问非公共属性。

You need to specify the flags parmeter by using this overload if you want properties other than public like: 如果您想要除public之外的属性,则需要使用此重载来指定flags parmeter:

type.GetProperty("Code",BindingFlags.Instance | 
                        BindingFlags.NonPublic |
                        BindingFlags.Public)

GetProperty(String) overload : GetProperty(String)重载

Searches for the public property with the specified name. 搜索具有指定名称的公共属性。

GetProperty(string name,BindingFlags bindingAttr) overload : GetProperty(string name,BindingFlags bindingAttr)重载

Searches for the specified property, using the specified binding constraints. 使用指定的绑定约束搜索指定的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM