我也試着找到這個東西。從這個問題,你給的想法得到IsOverriding
工作override
關鍵字。但是對於隱藏,我嘗試爲關鍵字new
創建IsHiding
。下面是基本C#OOP:
override
僅當基於方法包含abstract
或virtual
改性劑使用。
new
用於隱藏基礎的方法具有相同的名稱,但...
new
不能適用於abstract
基礎方法,因爲它產生編譯器錯誤。
- 然而,有趣的部分是
new
如果基本方法包含virtual
也可以應用於方法。
令人不滿的部分是我們可以隱藏或覆蓋virtual
方法。我們知道如果我們override
a virtual
方法GetBaseDefinition()
將返回基地MethodInfo
。但區分它的關鍵是GetBaseDefinition()
將返回相同的MethodInfo
而不是它基於MethodInfo
如果我們隱藏virtual
方法。
override
關鍵字是必須的,而new
僅用於抑制警告消息。所以我們可以通過IsAbstract
和IsVirtual
結合和BaseType
來區分override
和new
。
public static bool IsOverriding(this MethodInfo methodInfo)
{
if (methodInfo == null) throw new ArgumentNullException("methodInfo");
return methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType;
}
public static bool IsHiding(this MethodInfo methodInfo)
{
if (methodInfo == null) throw new ArgumentNullException("methodInfo");
if (methodInfo.DeclaringType == methodInfo.GetBaseDefinition().DeclaringType)
{
var baseType = methodInfo.DeclaringType.BaseType;
if (baseType != null)
{
MethodInfo hiddenBaseMethodInfo = null;
var methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static);
foreach (var mi in methods)
if (mi.Name == methodInfo.Name)
{
var miParams = mi.GetParameters();
var methodInfoParams = methodInfo.GetParameters();
if (miParams.Length == methodInfoParams.Length)
{
var i = 0;
for (; i < miParams.Length; i++)
{
if (miParams[i].ParameterType != methodInfoParams[i].ParameterType
|| ((miParams[i].Attributes^methodInfoParams[i].Attributes).HasFlag(ParameterAttributes.Out))) break;
// Simplified from:
//if (miParams[i].ParameterType != methodInfoParams[i].ParameterType
// || (miParams[i].Attributes.HasFlag(ParameterAttributes.Out) && !methodInfoParams[i].Attributes.HasFlag(ParameterAttributes.Out))
// || !(miParams[i].Attributes.HasFlag(ParameterAttributes.Out) && methodInfoParams[i].Attributes.HasFlag(ParameterAttributes.Out))) break;
}
if (i == miParams.Length)
{
hiddenBaseMethodInfo = mi;
break;
}
}
}
if (hiddenBaseMethodInfo != null && !hiddenBaseMethodInfo.IsPrivate) return true;
}
}
return false;
}
我測試它使用簡單的繼承,它的工作原理。我不考慮泛型方法..是..
編輯:我只是改變上面的代碼,因爲我忘了繼承類型可以包含這是不應該threated新新聲明的方法的想法。 IsHiding()
將首先確保它具有相同的(它看起來像新的),但需要看底座由DeclaringType.BaseType
聲明類型,如果使用相同的名稱的方法存在。
請注意,由於沒有BindingFlags.DeclaredOnly
,GetMethod()
會搜索整個基類型,所以不需要遞歸搜索到每個基類型。 BindingFlags.FlattenHierarchy
用於包括像這樣的抽象抽象基類的靜態方法:
public abstract class A
{
public static void Stat() { }
}
public abstract class B : A
{
}
public class C: B
{
public new static void Stat() { }
}
EDIT:剛纔修正以上IsHiding()
檢查重載基方法和防止AmbiguousMatchException
通過使用GetMethods()
而不是GetMethod()
。測試了具有不同參數的組合工作重載,拌入ref
,out
,params
和可選參數。用於重載簽名基於參數計數,參數類型和它的改性劑進行比較:
ref
或out
包含在簽名但兩者不能被重載到彼此。在最右邊的參數
- 返回類型,可選(默認值)和
params
應該
ref
相比可以忽略不計由ParameterType
本身(見調試期間,結束「&」),並沒有必要由IsByRef
比較而out
則由Attributes
旗標比較。當且僅當其中一個屬性標記爲Out
時,我使用簡化表達式按位異或來跳過循環,從而使簽名不同。與HasFlag
在.NET 4,不要混淆,它只是想確保Out
位爲1的XOR結果。
這似乎是一個重複的http://stackoverflow.com/questions/2932421/detect-if-a-method-was-overridden-using-reflection-c – 2011-04-21 15:51:28
@詹姆斯,嗯......這的確是一個類似的問題,雖然不完全一樣。我用'覆蓋'這個詞進行搜索,並且不幸的是帖子沒有找到,可能是因爲它使用了'重寫'這個詞。然而,那裏的答案並不適合我。 – JBSnorro 2011-04-21 16:02:14