如何将匿名类型的数据项转换为由相同类型组成的类

时间:2018-08-06 14:33:27

标签: c# asp.net linq-to-entities anonymous-types

如何将绑定到匿名类型的gridview中的数据项转换为相同类型的类?我不断收到InvalidCastException

这发生在RowDataBound中,使用

var row = (StationRow)e.Row.DataItem;

针对课程:

class StationRow
{
    public int StationID { get; set; }
    public string Has_Had_Allocation { get; set; }
    public string Inactive { get; set; }
    public int Block { get; set; }
    public int Session { get; set; }
    public int Rotation { get; set; }
    public int StationNumber { get; set; }
    public string Remove_Station { get; set; }
}

(格式化的)错误是:

{"Unable to cast object of type '<>f__AnonymousType24`8
[System.Int32,
System.String,
System.String,
System.Int32,
System.Int32,
System.Int32,
System.Int32,
System.String]' to type 'StationRow'."}

我认为我可以构建一个数据表并将linq结果泵入其中,然后绑定到表,使其成为DataRowView,但这似乎效率不高,因此,如果有人能指出我所缺少的内容,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

完全不建议使用此答案,在注释中建议从查询中返回正确的类是一个更好的主意。

MemberInfo上使用一些扩展方法来概括属性或字段的处理:

// ***
// *** Type Extensions
// ***
public static MemberInfo[] GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
    t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field | mi.MemberType == MemberTypes.Property).ToArray();

public static object GetValue(this MemberInfo member, object srcObject) {
    switch (member) {
        case FieldInfo mfi:
            return mfi.GetValue(srcObject);
        case PropertyInfo mpi:
            return mpi.GetValue(srcObject);
        default:
            throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
    }
}

public static void SetValue<T>(this MemberInfo member, object destObject, T value) {
    switch (member) {
        case FieldInfo mfi:
            mfi.SetValue(destObject, value);
            break;
        case PropertyInfo mpi:
            mpi.SetValue(destObject, value);
            break;
        default:
            throw new ArgumentException("MemberInfo must be of type FieldInfo or PropertyInfo", nameof(member));
    }
}

您可以编写一个扩展方法,将该属性或字段值复制到另一个对象中与(名称)匹配的属性或字段:

public static T ToType<T>(this object item) where T : new() {
    var ansObj = new T();
    var ansType = typeof(T);

    foreach (var prop in item.GetType().GetPropertiesOrFields()) {
            var destField = ansType.GetMember(prop.Name, BindingFlags.Public | BindingFlags.Instance).Single();
            destField.SetValue(ansObj, prop.GetValue(item));
    }

    return ansObj;
}

现在您可以创建一个新对象并复制值:

var row = e.Row.DataItem.ToType<StationRow>();