可能重复:
Is it possible to declare an anonymous type in C# with a variable/dynamic set of fields?
我构建了一个查询构建器,它通过检查用户在我的ASP.NET MVC3应用程序中设置的一些GET值来构造查询。此查询构建器可以添加排序,限制和过滤(WHERE子句),然后返回构造的查询。
然后,此查询将转到我的Dapper存储库,该存储库尝试使用以下命令执行查询:
using (IDbConnection connection = new MySqlConnection(ConnectionStringFactory.GetConnectionString(Database.Push)))
{
connection.Open();
return connection.Query<Notification>(query.QueryString,
new
{
someAnonymousStuffHere = SomeValue
});
}
但是,查询的参数(它是一个准备好的语句)需要放在匿名类型中。问题是:我不知道如何动态构造这个匿名类型。我现在所做的是将所有参数推送到查询构建器中的Dictionary中,其中键是属性的名称,值是,值。
我不能在查询构建器中定义匿名类型,因为构建器包含几个步骤,其中一些步骤未执行。所以有时我们有5个参数,有时候我们有3个参数,等等。
我希望我能够清楚地解释我的问题。请随时询问更多信息:)提前致谢!
答案 0 :(得分:15)
匿名类型只是一种方便,编译器可以“动态”为您创建一个类型,以节省您的输入。但是,它仍然是静态类型的。如果你需要一个“更聪明”的类型,其功能比你从匿名类型获得的更多,或者你需要传递该类型的实例,你需要创建一个“真实”类型,就像存在匿名类型之前一样。
另一种选择是使用dynamic
功能。您可以使用例如ExpandoObject
创建动态类型。这是一个关于如何使用它的小例子:
dynamic expando = new ExpandoObject();
expando.Name = "Martin";
if (((IDictionary<String, Object>) expando).ContainsKey("Name"))
Console.WriteLine(expando.Name);
expando实际上是一个美化的词典,而使用字典(就像你一样)可能会成为一个更好的选择。
答案 1 :(得分:3)
匿名类型在编译时仍然是静态类型的。我建议您查看dynamic
语言功能,或坚持使用字典。
这是一个从键/值字典中加载动态对象,然后像访问静态类型对象一样访问它的示例。
//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;
}
}