How to convert an anonymous type in Dynamic LINQ to a strong type

anonymous-types c# dynamic-linq linq

Question

This is a bit of a multi-faceted question, so let me just dive into the code with some explanation at the bottom.

Example Sample Data:

List<Encounter> input
Id, Facility, HospitalService, Field3, Field4, Field5, ...
 1,  1,       A,               ...,    ...,    ...
 2,  2,       A,               ...,    ...,    ...
 3,  1,       B,               ...,    ...,    ...
 4,  2,       B,               ...,    ...,    ...
 5,  1,       A,               ...,    ...,    ...
 5,  2,       A,               ...,    ...,    ...

What I want to do is query my data object and e.g. return back the distinct fields, e.g.

distinct Facility is 1, 2
distinct HospitalService is A, B
distinct pair is 1A, 2A, 1B, 2B

However, one gotcha is I want to return back a strongly typed object, and in this case, the same object as the input, in this case, the Encounter object, with all the other fields with empty or default values, e.g.

List<Encounter> output, with only fields of interest populated
Id, Facility, HospitalService, Field3, Field4, Field5, ...
 0,  1,       A,               "",     "",     ""
 0,  2,       A,               "",     "",     ""
 0,  1,       B,               "",     "",     ""
 0,  2,       B,               "",     "",     ""

With Standard LINQ, I can do this and it works.

    List<Encounter> sampleData = CreateSampleData();
    List<Encounter> rawResultFromStandardLinq =
        sampleData
            .GroupBy(e => new {e.Facility, e.HospitalService})
            .Select(e => new Encounter() { Facility = e.Key.Facility, HospitalService = e.Key.HospitalService})
            .ToList();

Question #1: In the above example, it is not dynamic. I had to know which object to create with the new keyword. Further, I had to know which fields to select/project. How can I do this dynamically? How can I project an anonymous type to a strong type?

e.g. I thought I could do something like this to use json serialization. This works, but I presume it would be very slow.

    var rawResultAsAnonymousType =
        sampleData
            .GroupBy(e => new { e.Facility, e.HospitalService })
            .Select(e => new { e.Key.Facility, e.Key.HospitalService }) 
            .ToList();

    string json = JsonConvert.SerializeObject(rawResultAsAnonymousType);
    var encountersFromJson = JsonConvert.DeserializeObject<List<Encounter>>(json);

Question #2: The next problem we have is that we want the query to be dynamic. i.e. we want to expose an interface that will let the client query the data to get whatever they want. For that purpose, we have turned to Dynamic LINQ.

Can someone help me to get this to work?

[Update: I can now do this for multiple columns]
            var rawResultFromDynamicLinq4 =
                DynamicQueryable
                    .GroupBy(_sampleData.AsQueryable(), @"new (Facility, HospitalService)", "it")
                    .Select("new (it.Key.Facility, it.Key.HospitalService)")
                    ;

[Before, I was trying to do this]
        var rawResultFromDynamicLinq =
            sampleData
                .GroupByMany("Facility", "HospitalService")
                //.Select(.... how do I get my object back?)
            ;

Some explanation:

Why are we doing it like this? It's largely irrelevant to the technical question, but if you must know, I work in healthcare and we are using the FHIR standards to query data, so we have to use the defined FHIR models. This means we can't just return back a List that contains distinct values of a particular field (e.g. for the client to create dropdown values for filtering the data).

1
0
9/11/2015 5:43:51 PM

Popular Answer

How can I project an anonymous type to a strong type?

Well, an anonymous type is a strong type - you just don't know the name of the type at compile time (hence "anonymous"). So sure, you can project to a different type and use tools like AutoMapper to map the anonymous type to a different type but you still have to know the fields at compile-time.

You might be able to do something like:

    sampleData
        .GroupBy(e => new {e.Facility, e.HospitalService})
        .Select(g => g.First())
        .ToList();

but it's not clear if that's exactly what you're looking for (and you still need to know the "grouping" fields at compile-time).

How can I do this dynamically?

What do you mean by "dynamically"? You mean have something that automatically sets the properties based on the destination type?

Can someone help me to get this to work?

Again, if you just want the first item that matches each grouping condition you can do

var rawResultFromDynamicLinq =
    sampleData
        .GroupByMany("Facility", "HospitalService")
        .Select(g -> g.First())
    ;
3
9/11/2015 3:56:22 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow