Ottieni la proprietà, come stringa, da un’espressione <Func >

Uso alcune espressioni fortemente tipizzate che vengono serializzate per consentire al mio codice UI di avere caratteri di ordinamento e ricerca fortemente tipizzati. Questi sono di tipo Expression<Func> e sono usati come tali: SortOption.Field = (p => p.FirstName); . Ho capito che funziona perfettamente per questo semplice caso.

Il codice che sto usando per analizzare la proprietà “FirstName” da lì in realtà sta riutilizzando alcune funzionalità esistenti in un prodotto di terze parti che utilizziamo e funziona alla grande, finché non iniziamo a lavorare con proprietà profondamente annidate ( SortOption.Field = (p => p.Address.State.Abbreviation); ). Questo codice ha alcuni presupposti molto diversi nella necessità di supportare proprietà profondamente annidate.

Per quanto riguarda ciò che fa questo codice, non lo capisco davvero e piuttosto che modificare quel codice, ho pensato di dover scrivere da zero questa funzionalità. Tuttavia, non conosco un buon modo per farlo. Sospetto che possiamo fare qualcosa di meglio che fare un ToString () ed eseguire l’analisi delle stringhe. Allora, qual è un buon modo per fare questo per gestire i casi banali e profondamente annidati?

Requisiti:

  • Data l’espressione p => p.FirstName ho bisogno di una stringa di "FirstName" .
  • Data l’espressione p => p.Address.State.Abbreviation ho bisogno di una stringa di "Address.State.Abbreviation"

Anche se non è importante per una risposta alla mia domanda, sospetto che il mio codice di serializzazione / deserializzazione possa essere utile a qualcun altro che trova questa domanda in futuro, quindi è qui sotto. Ancora una volta, questo codice non è importante per la domanda – ho solo pensato che potesse aiutare qualcuno. Nota che DynamicExpression.ParseLambda proviene dal materiale Dynamic LINQ e Property.PropertyToString() è l’argomento di questa domanda.

 ///  /// This defines a framework to pass, across serialized tiers, sorting logic to be performsd. ///  /// This is the object type that you are filtering. /// This is the property on the object that you are filtering. [Serializable] public class SortOption : ISerializable where TModel : class { ///  /// Convenience constructor. ///  /// The property to sort. /// Indicates if the sorting should be ascending or descending /// Indicates the sorting priority where 0 is a higher priority than 10. public SortOption(Expression<Func> property, bool isAscending = true, int priority = 0) { Property = property; IsAscending = isAscending; Priority = priority; } ///  /// Default Constructor. ///  public SortOption() : this(null) { } ///  /// This is the field on the object to filter. ///  public Expression<Func> Property { get; set; } ///  /// This indicates if the sorting should be ascending or descending. ///  public bool IsAscending { get; set; } ///  /// This indicates the sorting priority where 0 is a higher priority than 10. ///  public int Priority { get; set; } #region Implementation of ISerializable ///  /// This is the constructor called when deserializing a SortOption. ///  protected SortOption(SerializationInfo info, StreamingContext context) { IsAscending = info.GetBoolean("IsAscending"); Priority = info.GetInt32("Priority"); // We just persisted this by the PropertyName. So let's rebuild the Lambda Expression from that. Property = DynamicExpression.ParseLambda(info.GetString("Property"), default(TModel), default(TProperty)); } ///  /// Populates a  with the data needed to serialize the target object. ///  /// The  to populate with data.  /// The destination (see ) for this serialization.  public void GetObjectData(SerializationInfo info, StreamingContext context) { // Just stick the property name in there. We'll rebuild the expression based on that on the other end. info.AddValue("Property", Property.PropertyToString()); info.AddValue("IsAscending", IsAscending); info.AddValue("Priority", Priority); } #endregion }