ここでは、プロパティ自体ではなく、プロパティのメソッドの観点から扱う必要があります。実際にオーバーライドされるのはプロパティ自体ではなく、プロパティの get/set メソッドだからです。完全な解決策では、プロパティがないことを確認する必要がありますが、get メソッドを使用します。
多くのケースで発行された IL を見ると、ベース プロパティの 'get' メソッドはメタデータ トークンを持っています (これは C# コンパイラからのものです。他hidebysig
のメソッドはセマンティクスを隠しているメソッドによっては を発行しない場合があります。その場合、メソッドは名前で非表示になります):
non-virtual : .method public hidebysig specialname instance
virtual : .method public hidebysig specialname newslot virtual instance
派生したものには、次のトークンがあります。
override : .method public hidebysig specialname virtual instance
new : .method public hidebysig specialname instance
new virtual : .method public hidebysig specialname newslot virtual instance
new
このことから、非仮想ベース メソッドが非仮想new
メソッドと同じトークンを持ち、仮想ベース メソッドが同じトークンを持っているためかどうかをメソッドのメタデータ トークンだけから判断することはできないことがわかります。方法としてnew virtual
。
言えることは、メソッドがvirtual
トークンを持っているがトークンを持っていない場合newslot
、それは基本メソッドをシャドウするのではなくオーバーライドするということです。
var prop = typeof(ChildClass).GetProperty("TempProperty");
var getMethod = prop.GetGetMethod();
if ((getMethod.Attributes & MethodAttributes.Virtual) != 0 &&
(getMethod.Attributes & MethodAttributes.NewSlot) == 0)
{
// the property's 'get' method is an override
}
次に、「get」メソッドがオーバーライドではないことがわかったと仮定すると、基本クラスにシャドーしているプロパティがあるかどうかを知りたいとします。問題は、メソッドが別のメソッド テーブル スロットにあるため、シャドウしているメソッドと実際には直接的な関係がないことです。したがって、私たちが実際に言っているのは、「基本型には、シャドウイングの基準を満たすメソッドがありますか」ということです。これは、メソッドがhidebysig
名前によるものであるか非表示であるかによって異なります。
前者の場合、基本クラスに署名と正確に一致するメソッドがあるかどうかを確認する必要がありますが、後者の場合、同じ名前のメソッドがあるかどうかを確認する必要があるため、上記のコードを続けます。
else
{
if (getMethod.IsHideBySig)
{
var flags = getMethod.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
flags |= getMethod.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
var paramTypes = getMethod.GetParameters().Select(p => p.ParameterType).ToArray();
if (getMethod.DeclaringType.BaseType.GetMethod(getMethod.Name, flags, null, paramTypes, null) != null)
{
// the property's 'get' method shadows by signature
}
}
else
{
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
if (getMethod.DeclaringType.BaseType.GetMethods(flags).Any(m => m.Name == getMethod.Name))
{
// the property's 'get' method shadows by name
}
}
}
私はこれがほとんどの方法だと思いますが、それが正確に正しいとはまだ思いません。最初は、C# ではサポートされていないため、名前で非表示にすることに完全には慣れていません。私が使用するのはほとんどこれだけなので、インスタンス メソッドが静的メソッドをシャドウできることを示すコードが間違っている可能性があります。また、大文字と小文字の区別の問題についても知りません(たとえば、VBでは、両方が同じ署名を持ち、両方である場合にFoo
呼び出されるメソッドをシャドーすることができます-C#では答えはノーですが、VBで答えがイエスの場合、それはこの質問に対する答えが実際には非決定論的であることを意味します)。foo
hidebysig
ええと、これがどれだけ役立つかはわかりませんが、実際には私が思っていたよりもはるかに難しい問題であることを説明するためです (または、本当に明白なことを見逃している場合は知りたいです! )。しかし、うまくいけば、あなたがやろうとしていることを達成するのに役立つ十分なコンテンツが得られます.