このインターフェースがあると想像してください:
interface ITest
{
bool MyProperty { get; set; }
}
このクラスで実装:
class Test : ITest
{
bool ITest.MyProperty { get; set; }
}
次に、このプロパティを次のように追加しましょう(名前が同じTest
であることに注意してください)。
public bool MyProperty { get; set; }
プレーン でGetProperties()
は、明示的なインターフェイスの実装を取得できません (常にプライベート メンバーであるため)。
int count = new Test().GetType().GetProperties().Length; // It's 1!
Public
とメンバーの両方を含めると、両方NonPublic
が得られます。それらを区別するには、最初に名前に頼ることができます: 明示的な実装には、完全なインターフェイス名が含まれます (そのため、 を探すことができます。通常の.
プロパティには存在しません。これは許可された文字ではないためです)。
public static bool IsExplicitInterfaceImplementation(PropertyInfo property)
{
return property.Name.Contains(".");
}
少し素朴なので、追加のチェックが必要な場合があります。そのプロパティの get メソッドは次のようになると断言できます。
virtual
とですsealed
。
- です
private
。
- 少なくとも 1 つのドットが含まれます。
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;
}
もちろん、これらすべてのチェックが必要なわけではありません。最初の 2 つは、コンパイラによって生成されたコードのほとんどを除外するのに十分だと思います。
どのインターフェイスが明示的に実装されている可能性があるかがわかっている場合は、この質問が非常に便利であることがわかります。メソッドが特定のインターフェイスを実装しているかどうかを確認する方法
編集
コメントから私はこれについて考えましたが、それを行う適切な方法がないことがわかりました.CLRはルールを適用しません(AFAIK)。必要なのはインターフェイスメソッドとクラスメソッド間のリンクだけです(どのように呼び出されても)。私は推測します(ただし、他の言語では緩和または拡張される可能性があります。誰かがより多くのテストに貢献する場合は、この回答をwikiにします)このコードはほとんどの場合に機能する可能性があります(ヒントを提供してくれたAlxandrに感謝します):
メソッド (与えられた a MethodInfo
) が明示的なインターフェイスの実装であるかどうかをチェックする最初のジェネリック関数。
断言できないこと:
私たちが主張できること:
これはコードです:
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;
}
この補助関数を使用して、プロパティのチェックを行います。
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);
}