2011-01-25 12 views
10

Ho il seguente codice in un test di unitàReflection dice che il metodo di interfaccia è virtuale nel tipo implementato, quando non lo sono?

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

che io chiamo da

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

voglio assicurare che tutti i metodi dall'interfaccia sono dichiarate come virtuali. Il motivo è perché sto applicando un aspetto di spring.net e si applicherà solo ai metodi virtuali.

Il problema che sto avendo è che implMember.IsVirtual è sempre vero, anche quando non sono dichiarati come tali nel tipo di dichiarazione.

Cosa c'è di sbagliato nella mia logica TestMethodsOf?

Acclamazioni

risposta

18

Tutti i metodi dichiarati in un'interfaccia sono contrassegnati come virtual abstract, e tutti i metodi che implementano i metodi di interfaccia in classi sono contrassegnati come virtual final, in modo che il CLR sa che non si può semplicemente chiamare direttamente - ha a che fare ricerche vtable in fase di esecuzione chiamare la giusta implementazione. Le implementazioni dell'interfaccia sono ancora virtuali, ma non è possibile sovrascriverle poiché sono definitive.

A titolo di esempio, la definizione seguente C#:

public interface IInterface { 
    void Method(); 
} 

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

compila il seguente 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

eccellente! Così ho cambiato il mio codice per verificare IsFinal invece di IsVirtual e ora funziona correttamente. Grazie! –

3

Credo che quando si implementa un'interfaccia, i metodi si eredita dalla dell'interfaccia sono automaticamente contrassegnati come virtuale, in modo del logica bene, e non è necessario il test.

+0

Se provo ad ignorare i metodi del tipo di dichiarazione, non posso farlo. Anche l'aspetto dell'ereditarietà in questo caso non sta ignorando le mie chiamate al metodo, quindi non le riconosciamo come virtuali –

+0

vedi la migliore risposta di thecoop sul motivo per cui non puoi ignorarle ... – Massif

Problemi correlati