2009-06-25 9 views
22

Desidero conservare una proprietà tra i postback in un'applicazione ASP.Net. Al momento di fare questo:Ottieni il nome della proprietà all'interno del setter

public int MyIndex 
{ 
    get 
    { 
     return (int)Session[ToString() + "MyIndex"]; 
    } 
} 

ma preferirei qualcosa di simile:

public int MyIndex 
{ 
    get 
    { 
     return (int)Session[ToString() + #code_that_returns_property_name#]; 
    } 
} 

Setter omesso, ma semplicemente spinge valore nella sessione utilizzando la stessa stringa. C'è un modo per usare la riflessione o una soluzione diversa diversa?

+0

Sembra che finalmente abbiamo un po 'di [sintattico venuta caramelle] (http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6. aspx) per risolvere questo problema per noi: "Spesso è necessario fornire una stringa che chiami alcuni elementi del programma: quando si lancia un ArgumentNullException si desidera nominare l'argomento colpevole, quando si genera un evento PropertyChanged si desidera nominare la proprietà che è stata modificata, ecc. ". 'if (x == null) lanciare una nuova ArgumentNullException (nameof (x));' – JMD

risposta

24
public static int Dummy { 
    get { 
     var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4); 
     Console.WriteLine(propertyName); 
     return 0; 
    } 
} 
+1

GetCurrentMethod() ha restituito un System.ArgumentException per me ... –

+0

No, ha funzionato. Non so da dove provenga questa eccezione. Funziona bene ora. Proprio quello di cui avevo bisogno. –

+4

Per l'amore di Dio, no! Il risultato è cinque volte più lungo e 100 volte più oscuro di quello che ha sostituito! A meno che non cambierai continuamente idea su cosa chiamare quella proprietà, questa è un'idea ridicola. (... IMHO) –

13

No, non esiste un modo semplice per fare ciò che si vuole fare. Penso che tu sia molto meglio con il codice che hai già scritto.

Edit:Questa risposta ha ricevuto un bel paio di downvotes e faccio capire perché. Mentre è possibile fare ciò che l'OP vuole fare forse dovremmo tutti fermarci e pensare se sia o non sia consigliabile farlo. Per parafrasare le parole immortali di Dr. Ian Malcom, solo perché puoi fare qualcosa non significa che dovresti.

+0

Perché il down vote? è la risposta più sensata ... :) +1 da parte mia. –

+1

+1 da parte mia, questa è un'idea FANTASTICA. Se trovi che devi fare molto, e il nome continua a cambiare, quindi gestirlo diventa un peso, quindi utilizzare un file .tt per codegenare le dichiarazioni di proprietà o qualcosa del genere. –

+0

+1 per questo e la risposta accettata. Posso capire perché l'OP vorrebbe fare questo, e il fattore attenuante: se la proprietà in questione è solo una su 40, c'è qualcosa da dire per una singola implementazione che è disaccoppiata dai 40 nomi di proprietà hard-coded. Il fattore attenuante è, naturalmente, se l'OP sa che queste proprietà sono impostate una sola volta o un numero limitato di volte, le prestazioni a questo livello sono discutibili. Evitare l'ottimizzazione prematura. – JMD

7

È possibile utilizzare MethodInfo.GetCurrentMethod() nome per restituire il nome del metodo corrente:.

public int MyIndex 
{ 
    get 
    { 
     return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name]; 
    } 
} 

Dal proprietà sono implementate come metodi sotto il cofano, che restituirà un nome come "get_MyIndex". Se non si desidera che la parte "get_", è possibile sottostringa fuori un paio di caratteri:

public int MyIndex 
{ 
    get 
    { 
     return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name.Substring(4)]; 
    } 
} 
1

Si dovrebbe piuttosto utilizzare la proprietà ViewState del vostro controllo:

public int MyIndex { 
    get { 
     object index = ViewState["MyIndex"]; 
     return (null == index) ? -1 : (int)index; 
    } 
    set { 
     ViewState["MyIndex"] = value; 
    } 
} 
2

È possibile utilizzare un'espressione albero per ottenere il nome del membro. È un po 'duro ma funziona. Ecco il codice.

private string GetPropertyName<TValue>(Expression<Func<BindingSourceType, TValue>> propertySelector) 
{ 
    var memberExpression = propertySelector.Body as MemberExpression; 
    if (memberExpression != null) 
    { 
     return memberExpression.Member.Name; 
    } 
    else 
    { 
     return string.empty;  
    } 
} 

Con questo codice è possibile effettuare le seguenti operazioni

return (int)Session[ToString() + GetPropertyName(MyIndex)]; 

Codice spietatamente rubato dalla risposta di Romain sul thread

+0

Che soluzione elegante! +1 –

+0

Impossibile risolvere il simbolo 'BindingSourceType' Questo è un progetto ASP.Net 3.5 ... –

+0

Se si legge la risposta originale dall'altro thread, si dice che BindingSourceType è il nome della classe che contiene la proprietà. È necessario utilizzare il nome della classe a cui appartiene la proprietà MyIndex. – adrianbanks

9

Utilizzando CallerMemberName è molto più veloce e può essere copiato e incollato facilmente per ulteriori proprietà.

private static object GetSessionValue([CallerMemberName]string propertyName = "") 
{ 
    return Session[propertyName]; 
} 

private static void SetSessionValue(object value, [CallerMemberName]string propertyName = "") 
{ 
    Session[propertyName] = value; 
} 

public int MyIndex 
{ 
    get { return (int)GetSessionValue(); } 
    set { SetSessionValue(value); } 
} 
+0

Questa risposta è il modo migliore per funzionare poiché funziona in fase di compilazione e non in fase di runtime. – EvilTak

Problemi correlati