Search code examples
c#dynamic-linqvalueinjecter

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


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;
}

Solution

  • 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"