【问题标题】:How to cast an dataitem of anonymous type to a class made of its same types如何将匿名类型的数据项转换为由其相同类型组成的类
【发布时间】:2018-08-06 14:33:26
【问题描述】:

如何将绑定到匿名类型的网格视图中的数据项转换为由相同类型组成的类?我不断收到 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,但这似乎效率低下,所以如果有人能指出我所缺少的,我将不胜感激。

【问题讨论】:

  • 数据表是如何绑定的?为什么 ling 不投射到 StationRow 项目而不是匿名类型?
  • 您不能只将匿名类型隐式转换为某些已知类型。您将需要mappingexplicit conversion 或其他方式。或者只是使用 StationRow 而不是 anon 类型开始。
  • 要回答这个问题,没有办法仅仅因为属性名称对齐就转换为不同的类型。
  • 为什么要创建匿名类型对象而不是直接创建StationRow对象?
  • @GertArnold 如果您将其放入答案中,我会将其标记为正确

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


【解决方案1】:

完全不推荐这个答案,并且 cmets 中从查询中返回正确类的建议是一个更好的主意。

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>();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    • 2010-11-27
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多