2016-02-12 7 views
7

Si noti che questo potrebbe essere un duplicato di this question, non ne sono completamente sicuro.La riscrittura del contratto di codice non riesce con "Impossibile risolvere il riferimento membro"

Il mio problema è che ho un progetto di libreria di classi che ha un riferimento a una libreria di tipi di terze parti (COM). Voglio mettere contratti nelle metodi nella libreria di classi, in questo modo:

public class foo 
{ 
    public static int divide(TypeFromTypeLib tftl, int a, int b) 
    { 
     Contract.Requires<ArgumentException>(b != 0); 
     return a/b; 
    } 
} 

E poi avere un progetto client fare uso di questo metodo, per esempio

var n = foo.divide(null, 4, 2); 

ma mi piacerebbe anche il progetto client utilizzano anche i contratti in alcuni dei suoi metodi. Quindi, ho impostato le proprietà dei Contratti di codice su entrambi i progetti su "Esegui controllo contratto di runtime" (senza il quale si ottiene il runtime asserendo che è necessario questa impostazione).

Ora, quando ho poi provo a compilare il client, ottengo il seguente errore:

Could not resolve member reference: my_class_lib.foo::divide.

ccrewrite : error : Rewrite aborted due to metadata errors.

Quale sembra inevitabile - ogni volta che un metodo viene chiamato, che ha un tipo dalla terza libreria dei tipi festa questo accade . Rimuovi il tipo dalla firma del metodo e va bene.

Qualcuno può spiegare perché questo accade? E 'un indizio che la struttura del mio codice sia fondamentalmente difettosa (se sì, perché?), O è un capriccio di contratti di codice? Esiste una soluzione consigliata per questo problema?

+0

Ho ricevuto questo errore da ccrewrite, dai metodi in una libreria di prima parte che hanno incorporato i tipi di interoperabilità nella loro firma. – JamesFaix

+0

Ho avuto il mio progetto aperto in VS2015 e passato a VS2013 e il problema è andato via. Il compilatore di Roslyn sembra trattare i tipi di interoperabilità incorporati in modo diverso rispetto al vecchio compilatore, ma non riesco a trovare alcuna documentazione o conversazione al riguardo. Forse correlato: http://stackoverflow.com/questions/35641972/why-does-visual-studio-2015-throw-more-cs1769-compiler-errors-than-vs2013 – JamesFaix

+0

Quale versione dei contratti di codice hai installato? Fino al rilascio di v.1.10.10126.2-rc1 il 26 gennaio 2016 non ho mai ottenuto il controllo in fase di esecuzione dei contratti di codice che funzionano in Visual Studio 2015. Questa versione è la prima importante versione comunitaria di contratti di codice e indirizzi molto di problemi in sospeso. Può essere scaricato da: https://github.com/Microsoft/CodeContracts/releases. L'ho installato e il controllo runtime ora funziona ancora per me. –

risposta

2

Ad essere onesti non so perché ccrewrite ha un problema con i tipi di interoperabilità, ma posso darvi 3 soluzioni:

Soluzione 1

Questo è il più semplice:

  • Vai all'elenco di riferimenti per un progetto.
  • Trova libreria di tipi di terze parti.
  • Fare clic con il tasto destro.
  • Dal menu di scelta rapida selezionare Proprietà.
  • Cambia Inserisci tipi di intervallo da True a False.

Devi farlo per entrambi i progetti. Lo svantaggio di questa soluzione è che dopo una generazione si otterrà un ulteriore assembly di interoperabilità nella cartella bin.

Soluzione 2

Un'altra soluzione potrebbe essere quella di rimuovere tipi da una libreria di tipi di terze parti da un ovvero un'interfaccia pubblica:

public class foo 
{ 
    public static int divide(int a, int b) 
    { 
     return divide(null, a, b); 
    } 

    private static int divide(TypeFromTypeLib tftl, int a, int b) 
    { 
     Contract.Requires<ArgumentException>(b != 0); 
     return a/b; 
    } 
} 

Naturalmente si può fare solo se non lo fai è necessario utilizzare TypeFromTypeLib nel client.

Soluzione 3

Se è necessario utilizzare TypeFromTypeLib nel client è possibile scrivere un wrapper per questa classe cioè .:

public class MyTypeFromTypeLib 
{ 
    //... 
} 

public class foo 
{ 
    public static int divide(MyTypeFromTypeLib mytftl, int a, int b) 
    { 
     var tftl = new TypeFromTypeLib(); 
     //Map MyTypeFromTypeLib to TypeFromTypeLib 
     //... 
     return divide(tftl , a, b); 
    } 

    private static int divide(TypeFromTypeLib tftl, int a, int b) 
    { 
     Contract.Requires<ArgumentException>(b != 0); 
     return a/b; 
    } 
} 

Tuttavia, questa soluzione è ingombrante perché sono necessari ulteriori classi.

Problemi correlati