ZombieCode
ZombieCode

Reputation: 1661

C# How To Access Dynamic Variable Properties in C# and Razor

I have the name of a stored procedure stored in a database (and a couple of views). At run time I query the database and then run the needed query. Since I don't know the field names of the query nor do I have a known object to store the results to I use a dynamic variable

dynamic results = Respository.GetTableContents(); 
// not exactly the code but it conveys the point

The table would have an unknown number of fields, but for this example the field names are

Id, FirstName, Lastname  //(this is what the table would be returning) 

// Normally stored to a list of the model type
List<Users> resultsFromTable = ...

The resulting dynamic data can be accessed by

foreach(var r in result)
{
    string name = r.FirstName + " " + r.LastName;
    //.... Do something with the code, etc.
}

That is great if you know the property names. I don't know the property names.

How do I access the data of the dynamic variable without knowing the property name?

My main goal would be to use this in the view (razor).

Maybe I have approached the problem wrong and there is a better way. Any thoughts?

Upvotes: 0

Views: 1842

Answers (1)

Alex Filipovici
Alex Filipovici

Reputation: 32561

An alternative would be to use System.Reflection. Try this:

foreach (var r in results)
{
    string name, trimmedName = "";
    if (r.GetType() == typeof(ExpandoObject))
    { 
        name = ((IDictionary<string,object>)r).ToList()
            .Aggregate<KeyValuePair<string,object>, string>("", (s, p) =>
        {
            return s + " " + p.Value;
        });
        trimmedName = name.Trim();
    }
    else
    {
        PropertyInfo[] ps = r.GetType().GetProperties();
        name = ps.Aggregate<PropertyInfo, string>("", (s, p) =>
        {
            return s + " " + p.GetValue(r);
        });
        trimmedName = name.Trim();
    }
    // use the trimmedName 
    Console.WriteLine(trimmedName);
}

[EDIT] Based on @pwas' suggestio, here's an version of he code with an improved Cyclomatic Complexity:

foreach (var r in results)
{
    ProcessResult(r);
}

Where ProcessResult has 2 overloads:

static void ProcessResult(ExpandoObject r)
{
    string name, trimmedName = "";
    name = ((IDictionary<string, object>)r).ToList()
        .Aggregate<KeyValuePair<string, object>, string>("", (s, p) =>
        {
            return s + " " + p.Value;
        });
    trimmedName = name.Trim();
    FurtherProcess(trimmedName);
}

static void ProcessResult(object r)
{
    string name, trimmedName = "";
    PropertyInfo[] ps = r.GetType().GetProperties();
    name = ps.Aggregate<PropertyInfo, string>("", (s, p) =>
    {
        return s + " " + p.GetValue(r);
    });
    FurtherProcess(trimmedName);
}

private static void FurtherProcess(string trimmedName)
{
    Console.WriteLine(trimmedName);
}

Here is the improvement:

Type        Maintainability     Cyclomatic
            Index               Complexity
Program     54                  24
// After code optimization
Program     69                  16

Upvotes: 1

Related Questions