2011-01-25 19 views
10

Mam następujący kod w badanej jednostkiOdbicie mówi, że metoda interfejsu jest wirtualna w zaimplementowanym typie, gdy tak nie jest?

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; 
    } 

którą nazywam przez

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

Chcę zapewnić, że wszystkie metody z interfejsu są zadeklarowane jako wirtualny. Powodem jest to, że stosuję aspekt spring.net i dotyczy to tylko metod wirtualnych.

Problem, który mam, polega na tym, że implMember.IsVirtual jest zawsze prawdziwe, nawet jeśli nie są zadeklarowane jako takie w zadeklarowanym typie.

Co jest nie tak z moją logiką TestMethodsOf?

Cheers

Odpowiedz

18

Wszystkie metody zadeklarowane w interfejsie są oznaczone jako virtual abstract, a wszystkie metody implementujące metody interfejsu w klasach są oznaczone jako virtual final, więc CLR wie, że nie może po prostu wywoływać ich bezpośrednio - musi to zrobić w czasie wykonywania aby wywołać właściwą implementację. Implementacje interfejsu są nadal wirtualne, ale nie można ich zastąpić, ponieważ są ostateczne.

Jako przykład, definicja następujących C#:

public interface IInterface { 
    void Method(); 
} 

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

kompiluje z następującym 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() {} 
} 
+0

doskonałe! Więc zmieniłem kod, aby sprawdzić IsFinal zamiast IsVirtual i teraz działa dobrze. Dzięki! –

3

wierzę kiedy zaimplementować interfejs, metody można dziedziczyć z interfejsu są automatycznie oznaczane jako wirtualny, więc logika jest w porządku i nie trzeba test.

+0

Gdy próbuję zastąpić metody w rodzaju stwierdzającej, nie mogę tego zrobić. Również aspekt dziedziczenia w tym przypadku nie przesłania moich wywołań metod, więc nie wykrywa ich jako wirtualnych –

+0

zobacz lepszą odpowiedź co do tego, dlaczego nie można ich zastąpić ... – Massif

Powiązane problemy