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

笑着哭i 提交于 2019-11-30 03:57:56
jbtule

Dapper's creators were very aware of this problem. This kind of functionality is really needed for INSERT and UPDATE helpers.

The Query, Execute and QueryMultiple methods take in a dynamic parameter. This can either be an anonymous type, a concrete type or an object that implements IDynamicParameters.

public interface IDynamicParameters
{
    void AddParameters(IDbCommand command, Identity identity);
}

This interface is very handy, AddParameters is called just before running any SQL. Not only does this give you rich control over the parameters sent to SQL. It allows you to hook up DB specific DbParameters, since you have access to the command (you can cast it to the db specific one). This allows for support of Table Values Parameters and so on.

Dapper contains an implementation of this interface that can be used for your purposes called DynamicParameters. This allows you to both concatenated anonymous parameter bags and add specific values.

You can use the method AddDynamicParams to append an anonymous type.

var p = new DynamicParameters();
p.AddDynamicParams(new{a = "1"});
p.AddDynamicParams(new{b = "2", c = "3"});
p.Add("d", "4")
var r = cnn.Query("select @a a, @b b, @c c, @d d", p);
// r.a == 1, r.b == 2, r.c == 3, r.d == 4
Eric Lippert

In C#, I would like to figure out if it's possible to declare an anonymous type where the fields are not known until run-time.

Anonymous types are generated by the compiler. You want to know if the compiler will generate you a compiler-generated type with field types not known to the compiler. Clearly it cannot do so; as you correctly surmise, you are out of luck.

I've seen several questions on StackOverflow asking about extending anonymous types after they are declared ("extendo objects")

We usually call those "expando" objects.

If what you want to do is make an expando object based on a dictionary of key-value pairs, then use the ExpandoObject class to do that. See this MSDN article for details:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

If what you want to do is generate a bona-fide .NET class at runtime, you can do that too. As you correctly note, you need some fancy reflection to do so. What you want to do is make a collectible assembly (so-called because unlike a normal assembly, you generate it at runtime and the garbage collector will clean it up when you are done with it.)

See http://msdn.microsoft.com/en-us/library/dd554932.aspx for details on how to make a collectible assembly and emit a type into it using a TypeBuilder.

You can't use an anonymous type. Anonymous types are generated by the compiler rather than at run-time. You could certainly use dynamic though:

dynamic dynamicObj = new ExpandoObject();    
var objAsDict = (IDictionary<String, Object>)dynamicObj;

foreach(var item in paramList)
{
    objAsDict.Add(item.Item1, item.Item2);
}

You can then use dynamicObj as a regular object:

Console.WriteLine(dynamicObj.key1); // would output "value1"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!