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)
如果你包括两个Public和NonPublic成员,你会得到两者.为了区分它们,您可以首先依赖名称:显式实现将包含完整的接口名称(因此您可以查找a .,它不会存在普通属性,因为它不是允许的char):
public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
return property.Name.Contains(".");
}
Run Code Online (Sandbox Code Playgroud)
这有点天真,所以你可能想要一些额外的检查,你可以断言该属性的get方法将:
virtual和sealed.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)