2014-07-04 8 views
5

ho trovato this article sull'argomento e provato quanto segue:C# - Lanciare eccezioni costruttore di attributo

public class FailerAttr : Attribute { 
    public FailerAttr(string s) { 
     throw new Exception("I should definitely fail!"); 
    } 
} 

E nel progetto di unit test ho il seguente:

using Microsoft.VisualStudio.TestTools.UnitTesting; 

[TestClass] 
public class Test { 
    [TestMethod] 
    public void GoFail() { 
     // Make sure attribute will get initialized 
     new Failer(); 
    } 

    private class Failer { 
     [FailerAttr("")] 
     public int Prop { get; set; } 
    } 
} 

Quando eseguo il test , succede. Quindi, le domande sono:

  1. Perché non fallire?
  2. È davvero una cattiva idea gettare eccezioni dagli attributi? Perché penso di aver bisogno di

Alcune informazioni ambiente (nel caso in cui sia rilevante):

  • unit test vengono eseguiti tramite test runner unità di ReSharper (R # v8.2.0.2160)
  • studio visivo v11.0.61030. 0
+0

è possibile ottenere l'attributo utilizzando la riflessione? –

+0

@KarelFrajtak Non sono sicuro, non l'ho ancora provato. Proverò tra un minuto – Dethariel

+3

Il tuo commento '// Assicurati che l'attributo verrà inizializzato' è falso. Sarà costruito solo quando la Proprietà viene esaminata (attraverso la riflessione di solito). – Bun

risposta

9

Poiché gli attributi sono parte della definizione di classe a vostra disposizione in fase di esecuzione (si chiama anche "metadati" in geekspeak) CLR non crea un'istanza di loro a meno che qualche parte del vostro programma chiede per loro. Questo ha senso: perché preoccuparsi di spendere cicli di CPU per qualcosa a cui nessuno vuole accedere?

Per questo motivo, l'esecuzione del costruttore non avverrà mai a meno che non si chieda tale attributo.

Ecco un modo per chiedere un attributo che potrebbe rendere il vostro programma di fallire:

var attr = Attribute.GetCustomAttribute(typeof(Failer).GetProperty("Prop"), typeof(FailerAttr)); 

Questo codice rende CLR un'istanza FailerAttr, che innesca l'eccezione.

Demo on ideone.

Se non si conosce il tipo di attributo, è possibile recuperare tutti gli attributi in una volta con questa chiamata:

var allAttributes = Attribute.GetCustomAttributes(typeof(Failer).GetProperty("Prop")); 

Questo provoca un'eccezione così (demo).

+0

Contrassegnato come una risposta per esempi di codice su come ottenere un errore. Molte grazie! – Dethariel

+0

Non molto pertinente, ma se si utilizza .NET 4.5 o versioni successive, esistono metodi di estensione generici (è necessario 'utilizzare System.Reflection; '), quindi è possibile pronunciare' typeof (Failer) .GetProperty ("Prop"). GetCustomAttribute () '(singolo o null) o' typeof (Failer) .GetProperty ("Prop"). GetCustomAttributes () '(tutte le occorrenze, possibilmente vuote). –

+0

@JeppeStigNielsen Passiamo alla versione 4.5.1 e uso i miei metodi di estensione su 4.0 a tale scopo. Grazie per il consiglio, non lo sapevo – Dethariel

7

Gli attributi non vengono convertiti in codice eseguibile, vengono convertiti in metadati.

I metadati come questo non vengono utilizzati durante l'esecuzione normale, è solo se si inizia a utilizzare i metadati, come attraverso il riflesso, che il tipo di attributo ritorna in gioco.

Il costruttore o qualsiasi codice nell'attributo non viene eseguito durante la compilazione. Invece il tipo e i parametri del costruttore sono serializzati nei metadati e solo dopo l'ispezione mediante reflection il costruttore verrà effettivamente eseguito.

In altre parole, se si intende fallire al momento della compilazione, non è possibile.

Prova a cercare gli attributi utilizzando il reflection, a seconda dell'attributo l'oggetto è deserializzato dai metadati, il costruttore può o non può essere invocato, ma sicuramente non verrà richiamato applicandolo agli identificatori.

+0

Quindi il codice costruttore viene eseguito o meno (o dipende) quando l'attributo viene recuperato tramite reflection, ad esempio con 'typeof (Failer) .GetProperty (" Prop "). GetCustomAttributes()' o simile? –

+0

Viene eseguito quando si utilizza quel pezzo di riflessione, ma non al momento della compilazione. –

Problemi correlati