【问题标题】:C# How To Access Dynamic Variable Properties in C# and RazorC# 如何在 C# 和 Razor 中访问动态变量属性
【发布时间】:2013-08-11 00:29:08
【问题描述】:

我有一个存储在数据库中的存储过程的名称(和几个视图)。在运行时,我查询数据库,然后运行所需的查询。由于我不知道查询的字段名称,也没有已知对象来存储结果,因此我使用动态变量

dynamic results = Respository.GetTableContents(); 
// not exactly the code but it conveys the point

该表将包含未知数量的字段,但对于此示例,字段名称是

Id, FirstName, Lastname  //(this is what the table would be returning) 

// Normally stored to a list of the model type
List<Users> resultsFromTable = ...

生成的动态数据可以通过

访问
foreach(var r in result)
{
    string name = r.FirstName + " " + r.LastName;
    //.... Do something with the code, etc.
}

如果您知道属性名称,那就太好了。我不知道属性名称。

如何在不知道属性名的情况下访问动态变量的数据?

我的主要目标是在视图中使用它(剃刀)。

也许我处理问题的方法有误,但有更好的方法。有什么想法吗?

【问题讨论】:

  • 我不确定你的Respository.GetTableContents() 返回什么,但我会使用一个简单的System.Data.DataTable 然后我会使用foreach(DataColumn column in table.Columns)。在这种情况下,您将获得 DataColumn 类型,该类型可用于获取列的ColumnName 属性,包括其DataType、长度,当然还有它的值
  • 如果您的 Respository.GetTableContents() 返回某个基于 ExpandoObject 的类,您可以将其转换为 IDictionary&lt;string, Object&gt;
  • @cha 我认为这是可行的,但我们刚刚实现了这个奇特的数据库存储库。希望下面的答案会奏效。如果没有,那么我可能不得不说服他们接受这个解决方案。

标签: c# sql variables dynamic razor


【解决方案1】:

另一种方法是使用System.Reflection。试试这个:

foreach (var r in results)
{
    string name, trimmedName = "";
    if (r.GetType() == typeof(ExpandoObject))
    { 
        name = ((IDictionary<string,object>)r).ToList()
            .Aggregate<KeyValuePair<string,object>, string>("", (s, p) =>
        {
            return s + " " + p.Value;
        });
        trimmedName = name.Trim();
    }
    else
    {
        PropertyInfo[] ps = r.GetType().GetProperties();
        name = ps.Aggregate<PropertyInfo, string>("", (s, p) =>
        {
            return s + " " + p.GetValue(r);
        });
        trimmedName = name.Trim();
    }
    // use the trimmedName 
    Console.WriteLine(trimmedName);
}

[编辑] 基于 @pwas 的建议,这里是他的代码版本,具有改进的循环复杂度:

foreach (var r in results)
{
    ProcessResult(r);
}

ProcessResult 有 2 个重载:

static void ProcessResult(ExpandoObject r)
{
    string name, trimmedName = "";
    name = ((IDictionary<string, object>)r).ToList()
        .Aggregate<KeyValuePair<string, object>, string>("", (s, p) =>
        {
            return s + " " + p.Value;
        });
    trimmedName = name.Trim();
    FurtherProcess(trimmedName);
}

static void ProcessResult(object r)
{
    string name, trimmedName = "";
    PropertyInfo[] ps = r.GetType().GetProperties();
    name = ps.Aggregate<PropertyInfo, string>("", (s, p) =>
    {
        return s + " " + p.GetValue(r);
    });
    FurtherProcess(trimmedName);
}

private static void FurtherProcess(string trimmedName)
{
    Console.WriteLine(trimmedName);
}

以下是改进:

Type        Maintainability     Cyclomatic
            Index               Complexity
Program     54                  24
// After code optimization
Program     69                  16

【讨论】:

  • 很好,但我会将处理 r 拆分为单独的方法,以避免 if 声明。例如:准备方法public void ProcessResult(ExpandoObject eo) { \\ your code }public void ProcessResult(object o) { \\ your code },然后调用它foreach (var r in result) ProcessResult(r)。在这种情况下,r 是动态的,因此它的类型将在运行时解析并使用适当的重载方法。然后您可以轻松添加处理特定类型的方法。我的小题外话:)
  • @pwas,非常好的建议,我会根据它更新我的答案。
  • @pwas 在这种情况下,r 是动态的,因此它的类型将在运行时解析并使用适当的重载方法。 我不知道动态是这样的.不错!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 2017-11-07
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 2014-10-11
相关资源
最近更新 更多