lundi 10 mai 2021

Building a filter with Expression trees - accessing inherited properties

In my project, I use expression trees to build filters for database operations. This has worked flawlessly so far, but now some of the data structures have changed and I'm running into the following problem.

Imagine the object structure as:

class ClassA
{
   public ClassB PropertyX {get; set; }
}

class ClassB
{

}

class ClassC : ClassB
{
   public string PropertyY {get; set; }
}

class ClassD : ClassB
{
   public string PropertyZ {get; set; }
}

Now, when the user wants to build a filter, I would receive a dot-separated string, for example "PropertyX.PropertyZ". Which means that the PropertyX of ClassA has to be of type ClassD. But how do I build an expression that accesses this property?

I have found a solution here but it does not seem to work for me, maybe I am trying to use it wrong Expression Tree with Property Inheritance causes an argument exception

I tried to do my own implementation as well (code is not very nice, I was mainly just trying to see if this can even work) and the code still fails with the same exception - it tries to find PropertyZ of ClassB, but ClassB does not have that property defined, ClassD does.

//propertyNames is a list of property names that were originally provided as a dot-separated string
foreach (var propertyName in propertyNames)
{
   //returns all types inherited from the provided base type
   var inheritedTypes = _metadataMappingManager.GetMappedTypes(previousType);

   prop = previousType.GetProperty(propertyName);

   if (inheritedTypes != null)
   {
      foreach (var inheritedType in inheritedTypes)
      {
         var inheritedProp = inheritedType.GetProperty(propertyName);
         if (inheritedProp != null)
         {
            prop = inheritedProp;
            previousType = inheritedType;
            break;
         }
      }

      el = Expression.Property(el ?? parameter, (previousType).GetProperty(propertyName));
   }
   else
   {
      el = Expression.Property(el ?? parameter, (previousType).GetProperty(propertyName));
      previousType = prop.PropertyType;
   }
}




Aucun commentaire:

Enregistrer un commentaire