How to find the source property based on the name of a flattened property with ValueInjecter

StackOverflow https://stackoverflow.com/questions/10935016

  •  13-06-2021
  •  | 
  •  

سؤال

This is a counterpart to same question (but with AutoMapper). I use ValueInjecter and am interested if there is a solution.

Simplified code example:

// get a list of viewModels for the grid.
// NOTE: sort parameter is flattened property of the model (e.g. "CustomerInvoiceAmount" -> "Customer.Invoice.Amount"
// QUESTION: how do I get original property path so I can pass it to my repository for use with Dynamic LINQ?
public HttpResponseMessage Get(string sort)
{
    var models = _repo.GetAll(sort) // get a list of domain models
    var dto = _mapper.MapToDto(models); // get a list of view models that are flattened  via dto.InjectFrom<FlatLoopValueInjection>(models);

    var response = new HttpResponseMessage();
    response.CreateContent(vehicles);

    return response;
}
هل كانت مفيدة؟

المحلول

Well, I was able to cobble something up but would really like some input from community (and perhaps from @Chuck Norris, who wrote ValueInjecter)...

So to restate the issue....

  • You have your flattened view model that is being used in your view.
  • View has a grid whose columns are properties of said view model.
  • When user clicks on the column a sort=columnName is passed to controller
  • So now you need to decode flattened property name into original object graph in order to pass it to your repository for server side sorting (e.g. using Dynamic Expression APi, Dynamic LINQ or such)...

So if a Company has property called President of type Employee, and Employee has property called HomeAddress of type Address, and Address has string property called Line1 then:

"President.HomeAddress.Line1" will be flattened to property called "PresidentHomeAddressLine1" on your view model.

In order to user server side sorting Dynamic Linq needs dotted property path, not flattened one. I need ValueInjecter to unflatten the flat property only! not entire class.

Here is what I came up with (relevant logic extracted from a method that does other things:

// type is type of your unflattened domain model.
// flatProperty is property name in your flattened view model
public string GetSortExpressionFor(Type type, string flatPropertyPath)
{
    if (type == null || String.IsNullOrWhiteSpace(flatPropertyPath))
    {
        return String.Empty;
    }

    // use ValueInjecter to find unflattened property
    var trails = TrailFinder.GetTrails(flatPropertyPath, type.GetInfos(), typesMatch => true).FirstOrDefault();
    var unflatPropertyPath = (trails != null && trails.Any()) ? String.Join(".", trails) : String.Empty;

    return unflatPropertyPath;
}



// sample usage     
var unflatPropertyPath = GetSortExpressionFor(typeof(Company), "PresidentHomeAddressLine1");
// unflatPropertyPath == "President.HomeAddress.Line1"

نصائح أخرى

another way of doing this would be to use the TrailFinder

IEnumerable<IList<string>> GetTrails(string upn, IEnumerable<PropertyInfo> all, Func<Type, bool> f)

it's used by the UberFlatter like this:

var trails = TrailFinder.GetTrails(flatPropertyName, target.GetType().GetInfos(), f);

f Func check for the type of the end property to match a certain condition (probably in your case you could just return true)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top