使用未知属性类型创建动态对象

时间:2015-04-13 14:48:43

标签: c# asp.net-mvc reflection expandoobject dynamicobject

我想在ASP.NET MVC应用程序上创建一个通用的服务器端DataTable解决方案。我在每个Index视图上拥有的是一个JQuery数据表,其中对控制器进行AJAX调用以检索分页数据结果。执行的操作如下:

public JsonResult GetNewRequests([ModelBinder(typeof(DataTablesModelBinder))] DataTablesPageRequest pageRequest)
{
    var page = RequestsQuery(pageRequest); // Retrieves page of result from db and does any filtering + sorting
    var pageResponse = DataTablesFormat.PageResponse(pageRequest, page); // Formats response for jQuery DataTable to use
    return Json(pageResponse, JsonRequestBehavior.AllowGet); // Returns result
}

返回到jQuery DataTable控件的响应采用以下格式:

return new
{
    sEcho = pageRequest.Echo,
    iTotalRecords = report.TotalItems,
    iTotalDisplayRecords = report.TotalItems,
    sColumns = pageRequest.ColumnNames,
    aaData = results
};

我正在研究的部分是制定要返回的模型项列表,即:

aaData = results

results应该是任何模型对象的列表,包括其所有相关属性。我一直在尝试将reflectionExpandoObject一起使用来完成此解决方案,但无法找出机制:

public static object PageResponse(DataTablesPageRequest pageRequest, Page<object> report)
{
    List<object> results = new List<object>();

    foreach(var item in report.Items)
    {
        dynamic dynamicObject = new ExpandoObject();
        Type type = item.GetType();
        PropertyInfo[] properties = type.GetProperties();

        foreach(PropertyInfo property in properties)
        {
            Type propertyType = property.PropertyType;
            // Here is where I want to add a property with the correct name of the required type to the dynamic object
            dynamicObject[property.Name] = property.GetValue(item, null) as propertyType;
        }

        results.Add(dynamicObject);
    }

    return new
    {
        sEcho = pageRequest.Echo,
        iTotalRecords = report.TotalItems,
        iTotalDisplayRecords = report.TotalItems,
        sColumns = pageRequest.ColumnNames,
        aaData = results
    };
}

即使在打字时我也想出了一些东西。这部分我无法弄清楚:

dynamicObject[property.Name] = property.GetValue(item, null) as propertyType;

即设置属性类型,例如:DateTime

让我再说一遍。我想构建一个模型项列表。这可以是任何具有任意数量属性的模型类型,每个属性可以是任何类型(int,string,bool,DateTime等)。

2 个答案:

答案 0 :(得分:1)

正如Luaan已经评论过的那样,Convert.ChangeType就是你问题的答案。

但是,使用此功能对您来说无济于事。为什么?因为如果要将对象值分配给特定类型的变量(与object相对),则只有转换对象值才有用。

property.GetValue(item, null)的基础类型永远不会改变,因此尝试施放它无济于事。

另外,为什么不使用List<Dictionary<string, object>>甚至List<object[]>(我经常将其用于数据传输目的。使用dynamicExpandoObject没有意义这里。

答案 1 :(得分:1)

如果您希望能够动态添加属性,则需要将expando转换为IDictionary<string, object>

foreach(var item in report.Items)
{
    dynamic dynamicObject = new ExpandoObject();
    var dic = dynamicObject as IDictionary<string, object>;
    var properties = item.GetType().GetProperties();

    foreach(PropertyInfo property in properties)
    {
        dic[property.Name] = property.GetValue(item, null);
    }

    // At this stage the dynamicObject will contain properties with correct
    // names and types

    results.Add(dynamicObject);
}