2011-01-25 13 views
10

我在單元測試反射說,接口方法在實現類型中是虛擬的,當它們不是?

public bool TestMethodsOf<T, I>() 
    { 
    var impl = typeof(T); 
    var valid = true; 

    foreach (var iface in impl.GetInterfaces().Where(i => typeof(I).IsAssignableFrom(i))) 
    { 

    var members = iface.GetMethods(); 

    foreach (var member in members) 
    { 
    Trace.Write("Checking if method " + iface.Name + "." + member.Name + " is virtual..."); 
    var implMember = impl.GetMethod(member.Name, member.GetParameters().Select(c => c.ParameterType).ToArray()); 
    if (!implMember.IsVirtual) 
    { 
     Trace.WriteLine(string.Format("FAILED")); 
     valid = false; 
     continue; 
    } 

    Trace.WriteLine(string.Format("OK")); 
    } 
    } 
    return valid; 
    } 

我通過

Assert.IsTrue(TestMethodsOf<MyView, IMyView>()); 

我想,以確保所有從接口中的方法聲明爲虛擬調用下面的代碼。原因是因爲我在應用spring.net方面,它只適用於虛擬方法。

我遇到的問題是,implMember.IsVirtual始終是真實的,即使他們不聲明爲所以在聲明類型。

我的TestMethodsOf邏輯有什麼問題?

乾杯

回答

18

在接口中聲明的所有方法都被標記爲virtual abstract,並實現在類接口方法的所有方法都被標記爲virtual final,所以CLR知道它不能只是直接打電話給他們 - 它必須做在運行時查找的vtable調用正確的實現。界面的實現仍然是虛擬的,但是你不能覆蓋它們,因爲它們是最終的。

作爲一個例子,下面的C#定義:

public interface IInterface { 
    void Method(); 
} 

public class Class : IInterface { 
    public void Method() {} 
} 

編譯以下IL:

.class public interface abstract IInterface { 
    .method public abstract virtual instance void Method() {} 
} 

.class public Class extends [mscorlib]System.Object implements IInterface { 
    .method public specialname rtspecialname instance void .ctor() {} 
    .method public virtual final instance void Method() {} 
} 
3

,當你實現一個接口,我相信,從接口繼承你的方法被自動標記爲虛擬的,所以邏輯的很好,你不需要測試。

+0

如果我試圖覆蓋聲明類型的方法,我不能這樣做。此外,在這種情況下,繼承方面不重寫我的方法調用,所以沒有檢測到它們作爲虛擬 – 2011-01-25 12:03:03

+0

看到thecoop是更好的答案,爲什麼你不能覆蓋他們... – Massif 2011-01-25 12:06:36

相關問題