C#反射获取接口属性的实现属性

时间:2018-07-27 17:06:00

标签: c# reflection

我有一个接口,该接口已在属性上定义了自定义属性,我想从该接口的派生实例中检索相关属性。

public interface ITopicProcessor<T>
{
    [TopicKey]
    string TopicName { get; }

    [OtherAttribute]
    string OtherProperty { get; }

    void Process(T message);
}

public class MyClassProcessor : ITopicProcessor<MyClass>
{
    public string TopicName => "MyTopic";

    public string OtherProperty => "Irrelevant";

    public void Process(MyClass message)
    {
    }
}

我可以通过以下内容接近-主要问题是派生的接口类型似乎没有与通用类型定义相同的自定义属性。我很确定这部分是由于需要使用基础方法实现而不是直接使用属性值

// iType is typeof(ITopicProcessor<MyClass>)
// I also have access to the generic type definition if need be - i.e. typeof(ITopicProcessor<>)
Func<Type, string> subscriberTypeToTopicKeySelector = iType =>
{
    // Creating an instance via a dependency injection framework
    var instance = kernel.Get(iType);
    var classType = instance.GetType();

    var interfaceMap = classType.GetInterfaceMap(iType);
    // interfaceMap.InterfaceMethods contains underlying get_property method, but no custom attributes
    var interfaceMethod = interfaceMap.InterfaceMethods
                                      .Where(x => x.HasAttribute<TopicKeyAttribute>())
                                      .ToList();
    var classMethodInfo = interfaceMap.TargetMethods[Array.IndexOf(interfaceMap.InterfaceMethods, interfaceMethod)];

    return classMethodInfo.Invoke(instance, BindingFlags.Default, null, null, CultureInfo.CurrentCulture)
                          .ToString();
};

2 个答案:

答案 0 :(得分:1)

实现接口不是从类继承。这就是为什么此类专有技术不会从接口传播到类的原因。参见:bradwilson.typepad.com/blog/2011/08/interface-attributes-class-attributes.html

但是有解决方法:Can a C# class inherit attributes from its interface?

答案 1 :(得分:0)

在@thehennyy的评论中,我得到了一些不仅有用的东西,而且可以处理应用于属性或方法的[TopicKey]属性。对于我的需求,我只希望它在界面中出现一次,但是其他任何人都可以根据自己的需要扩展此解决方案

subscriberTypeToTopicKeySelector = iType =>
{
    var instance = kernel.Get(iType);
    var classType = instance.GetType();
    var interfaceMap = classType.GetInterfaceMap(iType);

    var iTopicKeyPropertyGetMethods = iType.GetProperties()
                                           .Where(x => x.HasAttribute<TopicKeyAttribute>())
                                           .Select(x => x.GetMethod);
    var iTopicKeyMethods = iType.GetMethods()
                                .Where(x => x.HasAttribute<TopicKeyAttribute>())
                                .Union(iTopicKeyPropertyGetMethods);

    var indexOfInterfaceMethod = Array.IndexOf(interfaceMap.InterfaceMethods, iTopicKeyMethods.Single());
    var classMethodInfo = interfaceMap.TargetMethods[indexOfInterfaceMethod];

    return classMethodInfo.Invoke(instance, BindingFlags.Default, null, null, CultureInfo.CurrentCulture)
                          .ToString();
};