【问题标题】:Exclude interface implementation members through reflection通过反射排除接口实现成员
【发布时间】:2017-01-07 17:01:42
【问题描述】:

我有以下接口和实现:

public interface INew
{
    string TestString { get; }
}

public class PurchaseOrder : INew
{
    public string OrderNo { get; set; }

    public string TestString
    {
        get { return "This is a test string"; }
    }
}

我正在尝试使用以下代码反映PurchaseOrder 对象的OrderNo 部分:

var props = p.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy);
foreach (var prop in props)
{
    Console.WriteLine(prop.Name);
}

我的输出也返回了TestString 属性。我已经搜索了排除已实现接口成员的方法,但只能找到包含它的项目。谁能告诉我如何排除这些项目?

【问题讨论】:

标签: c# reflection interface


【解决方案1】:

这是一个使用 GetInterfaceMap 方法的解决方案:

var interfaceMethods = typeof(PurchaseOrder)
    .GetInterfaces()
    .Select(x => typeof(PurchaseOrder).GetInterfaceMap(x))
    .SelectMany(x => x.TargetMethods).ToArray();

var propsNotFromInterface= typeof(PurchaseOrder)
    .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy)
    .Where(x => !x.GetAccessors(true).Any(y => interfaceMethods.Contains(y))).ToArray();

Console.WriteLine(propsNotFromInterface.Length);

你可以很容易地把它重构为一个泛型方法。

【讨论】:

  • (BindingFlags)62?
  • Ops,它是我使用的调试快捷方式,用于Public | NonPublic | Instance | Static
  • 非常适合我,即使实现了多个接口!谢谢:)
【解决方案2】:

您可以尝试排除INew 中定义的属性,例如:

PurchaseOrder p = new PurchaseOrder();
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy;
PropertyInfo[] iNewPropertyInfos = typeof(INew).GetProperties(bindingFlags);
var props = p.GetType().GetProperties(bindingFlags).Where(x => iNewPropertyInfos.All(y => y.ToString() != x.ToString()));
foreach (var prop in props)
{
    Console.WriteLine(prop.Name);
}

更新。

更通用的方法是将逻辑转移到通用函数中:

private static IEnumerable<PropertyInfo> GetPropertiesExcept<T>(object p)
{
    BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
                                BindingFlags.FlattenHierarchy;
    PropertyInfo[] iNewPropertyInfos = typeof (T).GetProperties(bindingFlags);
    return p.GetType().GetProperties(bindingFlags).Where(x => iNewPropertyInfos.All(y => y.ToString() != x.ToString()));
}

及用法:

PurchaseOrder p = new PurchaseOrder();
IEnumerable<PropertyInfo> propertiesExcept = GetPropertiesExcept<INew>(p);

【讨论】:

  • 谢谢,这确实有效,但是我希望有一个更通用的方法 - 我有几个接口。但是现在它会让我前进!
  • 感谢您的更新,但是如果我有一个实现多个显式实现的接口的类,它们仍然存在(完全限定名称)。
猜你喜欢
  • 2010-09-09
  • 2023-02-15
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
  • 2015-10-21
  • 2016-01-29
相关资源
最近更新 更多