如何动态地向匿名对象添加属性?

时间:2011-10-04 12:14:23

标签: c# .net asp.net asp.net-mvc-3

  

可能重复:
  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个参数,等等。

我希望我能够清楚地解释我的问题。请随时询问更多信息:)提前致谢!

2 个答案:

答案 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;
    }
}