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.
In C# 4.0, a new type is introduced that is known as a dynamic type. It is used to avoid the compile-time type checking. The compiler does not check the type of the dynamic type variable at compile time, instead of this, the compiler gets the type at the run time.
Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using var. The type name cannot be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type.
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.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With