如何知道MemberInfo是否是属性的显式实现

Kar*_*sar 15 .net c# reflection

想象一下,我有下面的代码.我怎样才能通过反思得到MemberInfo/PropertyInfo"明确"的实施Test.Name

另外,有没有办法以编程方式知道a MemberInfo是接口属性的显式实现?

public interface ITest
{
    string Title { get; set; }
}

public interface IExplicit
{
    string Name { get; set; }
}

public class Test : ITest,IExplicit
{

    public string Title { get; set; }

    string IExplict.Name
    {
        get
        {
            return this.Title;

        }
        set
        {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Adr*_*tti 13

想象一下,你有这个界面:

interface ITest
{
    bool MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在这个类中实现:

class Test : ITest
{
    bool ITest.MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在让我们添加这个属性Test(注意它们具有相同的名称):

public bool MyProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

使用plain, GetProperties()您将无法获得显式接口实现(因为它始终是私有成员):

int count = new Test().GetType().GetProperties().Length; // It's 1!
Run Code Online (Sandbox Code Playgroud)

如果你包括两个PublicNonPublic成员,你会得到两者.为了区分它们,您可以首先依赖名称:显式实现将包含完整的接口名称(因此您可以查找a .,它不会存在普通属性,因为它不是允许的char):

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    return property.Name.Contains(".");
}
Run Code Online (Sandbox Code Playgroud)

这有点天真,所以你可能想要一些额外的检查,你可以断言该属性的get方法将:

  • virtualsealed.
  • private.
  • 至少包含一个点.
  • 不会以get_或开头_set

我们改变代码:

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    // This check is not mandatory and not cross-languages.
    // How this method is named may vary
    if (!property.Name.Contains("."))
        return false;

    if (property.Name.StartsWith("get_"))
        return false;

    if (!property.GetMethod.IsFinal)
        return false;

    if (!property.GetMethod.IsVirtual)
        return false;

    if (!property.GetMethod.IsPrivate)
        return false;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

当然不是所有这些检查都是必需的,我认为前两个足以排除大多数编译器生成的代码.

如果您知道可以明确实现哪个接口,那么您将在此处找到这个问题非常有用:如何查找方法是否正在实现特定接口

编辑
从评论我想到这一点,我发现没有一个正确的方法来做到这一点,CLR不应用任何规则(AFAIK)因为所需要的只是接口方法和类方法之间的链接(无论如何调用它).我想(但是对于其他语言可能会放宽或扩展,如果有人会提供更多测试,我会将此答案作为维基)这个代码在大多数情况下都可以工作(感谢Alxandr的提示):

第一个通用函数,用于检查方法(给定的a MethodInfo)是否是显式接口实现.

我们不能断言:

  • 我们不能使用name(检查,例如".")因为它依赖于实现(C#使用interfaceName.methodName,但其他语言不使用).

  • 我们不能依赖于私有检查,因为(例如)在C++/CLI中它可以是一个公共方法(具有另一个名称)而且一个接口可以被"黑客"为内部但是实现者是公共的(所以方法赢了)也不公开.

我们可以断言:

  • 显式接口实现始终是密封和虚拟的.也许它"不适用于所有语言,所以我们可以放松这个规则.

  • 如果一个方法与它实现的接口中声明的方法名称不同,那么它就是一个显式实现.

这是代码:

public static bool IsExplicitInterfaceImplementation(MethodInfo method)
{
    // Check all interfaces implemented in the type that declares
    // the method we want to check, with this we'll exclude all methods
    // that don't implement an interface method
    var declaringType = method.DeclaringType;
    foreach (var implementedInterface in declaringType.GetInterfaces())
    {
        var mapping = declaringType.GetInterfaceMap(implementedInterface);

        // If interface isn't implemented in the type that owns
        // this method then we can ignore it (for sure it's not
        // an explicit implementation)
        if (mapping.TargetType != declaringType)
            continue;

        // Is this method the implementation of this interface?
        int methodIndex = Array.IndexOf(mapping.TargetMethods, method);
        if (methodIndex == -1)
            continue;

        // Is it true for any language? Can we just skip this check?
        if (!method.IsFinal || !method.IsVirtual)
            return false;

        // It's not required in all languages to implement every method
        // in the interface (if the type is abstract)
        string methodName = "";
        if (mapping.InterfaceMethods[methodIndex] != null)
            methodName = mapping.InterfaceMethods[methodIndex].Name;

        // If names don't match then it's explicit
        if (!method.Name.Equals(methodName, StringComparison.Ordinal))
            return true;
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

使用此辅助功能来检查属性:

public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
    // At least one accessor must exists, I arbitrary check first for
    // "get" one. Note that in Managed C++ (not C++ CLI) these methods
    // are logically separated so they may follow different rules (one of them
    // is explicit and the other one is not). It's a pretty corner case
    // so we may just ignore it.
    if (property.GetMethod != null)
        return IsExplicitInterfaceImplementation(property.GetMethod);

    return IsExplicitInterfaceImplementation(property.SetMethod);
}
Run Code Online (Sandbox Code Playgroud)

  • 我想我可能确实找到了更好的解决方案.检查方法是否通过使用interface-maps(http://stackoverflow.com/questions/7379276/how-to-find-if-a-method-is-implementing-specific-interface)实现接口,并且是私有的(或者说VB/C++的名称不同,你有一个公共方法实现一个带有另一个名字的接口方法,如果这确实可行的话). (2认同)