2015-10-14 27 views
10

Sto usando .NET4.5 e C# ho immaginato la creazione di metodo di estensione che mi avrebbe permesso di passare una proprietà dell'oggetto e se Id di quell'oggetto è 0 allora return null altrimenti restituisce quel valore della proprietà.metodo di estensione che accetta Espressione <Func<T>> espressione come parametro

Non ho potuto fare nessun problema con la riflessione, quindi considera più questo esercizio di allenamento e non io che sto cercando di risolvere il problema.

metodo di estensione Attualmente è seduto in static classe guardando come questo:

public static object GetNullIfNotSet(this WillAnswer answer, Expression<Func<WillAnswer>> expression) 
    { 
     if (answer.Id == 0) return null; 
     return expression.Compile()(); 
    } 

Il modo in cui voglio essere in grado di usarlo è seguito (risposta è di tipo WillAnswer):

var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets) 

Tuttavia mi dà errore di compilazione:

Error 1 Delegate 'System.Func' does not take 1 arguments C:\hg\Website\Areas\Wills\ViewModel\Answers.cs 38 59 Website enter image description here

Il che mi fa arrabbiare perché non penso di passare alcun argomento (vero?). Potrebbe piacere a qualcuno più intelligente di me stesso spiegare quale delle mie aspettative è sbagliata.

Nel caso in cui non fossi chiaro ripeterò. Quello che voglio è poter chiamare var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets) e ottenere null se Id di answer è 0.

+1

Come altri ho sottolineato, non hai bisogno di un'espressione. La fonte del tuo errore è il fatto che tu abbia definito il tuo func sbagliato, comunque.Probabilmente vuoi qualcosa di simile a Func (con oggetto che è il tipo restituito). –

+1

chiamalo in questo modo: 'answer.GetNullIfNotSet (() => (((Func ) (() => answer.HasBusinessAssets))()));' Che casino! torna alla risposta di haim770 :-) –

+0

Se hai accesso all'oggetto di cui stai accedendo alla proprietà quando chiami il metodo, che fai come un'estensione sull'oggetto stesso, allora perché non passare semplicemente la proprietà invece di un 'Func'? – user2697817

risposta

14

Non c'è bisogno di Expression a tutti, basta usare Func<WillAnswer, TProp>:

public static TProp GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func) 
{ 
    if (answer.Id == 0) return default(TProp); 
    return func(answer); 
} 

Si prega di notare, che questo non sarà sempre tornare null ma il valore di default (nel caso in cui la proprietà è un valore-tipo).

Update (secondo la vostra richiesta):

Al fine di essere in grado di restituire null per tutte le proprietà passarono, la firma del metodo è stato cambiato per tornare object invece:

public static object GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func) 
{ 
    if (answer.Id == 0) return null; 
    return func(answer); 
} 

Ma, perderai i benefici dei generici e finirai con cast espliciti a Nullable<T>:

var emptyIfNewObject = (bool?)answer.GetNullIfNotSet(o => o.HasBusinessAssets) 

Quale è meno ideale.

+0

Ottima risposta, ma come faccio a restituire null? –

+0

Per restituire sempre 'null', il compilatore dovrà assicurarsi che la proprietà passata' x => x.SomeProp' sia un tipo di riferimento. Questo può essere fatto aggiungendo un vincolo generico, ma significa che non sarà possibile restituire 'x => x.SomeInt' (ad esempio). E 'quello di cui hai bisogno? – haim770

+0

Potresti fare una leggera aleterazione nella tua risposta invece di 'TProp' return' object' questo permette di restituire null' oggetto statico pubblico GetNullIfNotSet (questo WillAnswer answer, Func func) { if (answer. Id == 0) restituisce null; return func (risposta); } ' –

7

Sembra che un Func<WillAnswer, T> non avete bisogno di un espressione:

public static T GetDefaultIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) { 
    if (null == answer) 
     throw new ArgumentNullException("answer"); 
    else if (null == func) 
     throw new ArgumentNullException("func"); 

    return answer.Id == 0 ? return default(T) : func(answer); 
    } 

EDIT: se si desidera garantirenull è possibile limitare generico T:

 public static T GetNullIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) 
     where T: class { // no structs here 
     if (null == answer) 
      throw new ArgumentNullException("answer"); 
     else if (null == func) 
      throw new ArgumentNullException("func"); 

     return answer.Id == 0 ? return null : func(answer); 
    } 
+0

Vorrei anche suggerire di rinominare il nome del metodo in qualcosa come "GetDefaultIfNotSet', perché la semantica è cambiata - non è possibile restituire il valore' null' per la proprietà 'bool'. –

+0

@Sergey Kolodiy: grazie! Ho modificato la risposta, 'GetDefaultIfNotSet' è un nome molto migliore. –

+0

@SergeyKolodiy ma ho bisogno di null, questa è l'essenza della domanda –