J'utilise fortement typées expressions qui se sérialisé pour permettre à mon code de l'INTERFACE utilisateur d'avoir fortement typées de tri et de recherche d'expressions. Ce sont de type Expression<Func<TModel,TProperty>>
et sont utilisés en tant que tels: SortOption.Field = (p => p.FirstName);
. J'ai obtenu ce travail parfaitement pour ce cas simple.
Le code que j'utilise pour l'analyse de la "FirstName" propriété de, il est en fait de la réutilisation de certaines fonctionnalités existantes dans un tiers des produits que nous utilisons et il fonctionne très bien, jusqu'à ce que nous commençons à travailler avec profondément propriétés imbriquées(SortOption.Field = (p => p.Address.State.Abbreviation);
). Ce code a certains très différentes hypothèses dans la nécessité de soutenir profondément propriétés imbriquées.
Comme pour ce que ce code fait, je ne comprends pas vraiment, et plutôt que de changer le code, j'ai pensé que je devrais écrire à partir de zéro cette fonctionnalité. Cependant, je ne sais pas d'une bonne façon de le faire. Je pense que nous pouvons faire quelque chose de mieux que de faire un ToString() et d'effectuer le traitement de chaîne. Donc, ce est une bonne façon de le faire pour gérer le trivial et profondément imbriquée cas?
Exigences:
- Compte tenu de l'expression
p => p.FirstName
- je besoin d'une chaîne d'"FirstName"
. - Compte tenu de l'expression
p => p.Address.State.Abbreviation
- je besoin d'une chaîne d'"Address.State.Abbreviation"
Alors que ce n'est pas important pour une réponse à ma question, je soupçonne mon sérialisation/désérialisation code pourrait être utile à quelqu'un d'autre qui trouve cette question dans l'avenir, de sorte qu'il est ci-dessous. Encore une fois, ce code n'est pas important pour la question - j'ai juste pensé qu'il pourrait aider quelqu'un. Notez que DynamicExpression.ParseLambda
provient de la Dynamique LINQ trucs et Property.PropertyToString()
est ce que cette question est à propos.
/// <summary>
/// This defines a framework to pass, across serialized tiers, sorting logic to be performed.
/// </summary>
/// <typeparam name="TModel">This is the object type that you are filtering.</typeparam>
/// <typeparam name="TProperty">This is the property on the object that you are filtering.</typeparam>
[Serializable]
public class SortOption<TModel, TProperty> : ISerializable where TModel : class
{
/// <summary>
/// Convenience constructor.
/// </summary>
/// <param name="property">The property to sort.</param>
/// <param name="isAscending">Indicates if the sorting should be ascending or descending</param>
/// <param name="priority">Indicates the sorting priority where 0 is a higher priority than 10.</param>
public SortOption(Expression<Func<TModel, TProperty>> property, bool isAscending = true, int priority = 0)
{
Property = property;
IsAscending = isAscending;
Priority = priority;
}
/// <summary>
/// Default Constructor.
/// </summary>
public SortOption()
: this(null)
{
}
/// <summary>
/// This is the field on the object to filter.
/// </summary>
public Expression<Func<TModel, TProperty>> Property { get; set; }
/// <summary>
/// This indicates if the sorting should be ascending or descending.
/// </summary>
public bool IsAscending { get; set; }
/// <summary>
/// This indicates the sorting priority where 0 is a higher priority than 10.
/// </summary>
public int Priority { get; set; }
#region Implementation of ISerializable
/// <summary>
/// This is the constructor called when deserializing a SortOption.
/// </summary>
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<TModel, TProperty>(info.GetString("Property"), default(TModel), default(TProperty));
}
/// <summary>
/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param>
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param>
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
}