How to add properties to anonymous object dynamically?

29,214

Solution 1

Anonymous types are simply a convenience where the compiler can create a type for you "on the fly" to save you some typing. However, it is still statically typed. If you need a "smarter" type with more functionality than you get from an anonymous type or if you need to pass instances of the type around you need to create a "real" type as you would before anonymous types existed.

Another option is to use the dynamic feature. You can create a dynamic type by using for instance ExpandoObject. Here is a small example on how you can use it:

dynamic expando = new ExpandoObject();
expando.Name = "Martin";
if (((IDictionary<String, Object>) expando).ContainsKey("Name"))
  Console.WriteLine(expando.Name);

The expando is really a glorified dictionary and using a dictionary instead (like you do) might turn out to be a better option.

Solution 2

Anonymous types are still statically typed at compile time. I'd suggest looking into the dynamic language features, or sticking with your dictionary.

Here is an example of loading up a dynamic object from a dictionary of key/values, then accessing it as if it was a statically typed object.

//linqpad
void Main()
{
    IDictionary<string,object> items = new Dictionary<string,object>();
    items.Add("test","123");

    dynamic props = DynamicProperties.LoadFromDictionary(items);

    string item = props.test;

    item.Dump();
}


public class DynamicProperties : DynamicObject
{
    private DynamicProperties(){}

    private Dictionary<string, object> dictionary = new Dictionary<string, object>();

    public static DynamicProperties LoadFromDictionary(IDictionary<string,object> Dictionary)
    {
        dynamic dprop = new DynamicProperties();
        foreach(var item in Dictionary)
        {
            dprop.dictionary.Add(item.Key.ToLower(),item.Value);
        }
        return dprop;
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        string name = binder.Name.ToLower();
        Console.WriteLine("Trying to get " + name);
        return this.dictionary.TryGetValue(name,out result);
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        Console.WriteLine("TrySetMember: " + value.ToString());
        this.dictionary[binder.Name.ToLower()] = value;
        return true;
    }
}
Share:
29,214
Leon Cullens
Author by

Leon Cullens

Available for freelance jobs. Contact me at [email protected].

Updated on June 23, 2020

Comments

  • Leon Cullens
    Leon Cullens almost 4 years

    Possible Duplicate:
    Is it possible to declare an anonymous type in C# with a variable/dynamic set of fields?

    I've built a query builder that constructs a query by examining some GET values that the user has set in my ASP.NET MVC3 application. This query builder can add sorting, limiting and filtering (the WHERE clause) and then returns the constructed query.

    This query then goes to my Dapper repository that tries to execute the query with:

    using (IDbConnection connection = new MySqlConnection(ConnectionStringFactory.GetConnectionString(Database.Push)))
    {
        connection.Open();
    
        return connection.Query<Notification>(query.QueryString,
                                              new 
                                              {
                                                  someAnonymousStuffHere = SomeValue
                                              });
    }
    

    However, the parameters for the query (it's a prepared statement) need to be put in an anonymous type. The problem is: I don't know how to construct this anonymous type dynamically. What I do now is pushing all the parameters into a Dictionary<string, string> in the query builder, where the key is the name of the property and the value is, well, the value.

    I can't just define an anonymous type in my query builder because the builder consists of several steps, of which some aren't executed. So sometimes we have 5 parameters, sometimes we have 3 parameters, etc.

    I hope I explained my problem clear enough.