【问题标题】:Dynamically copying generic objects动态复制通用对象
【发布时间】:2013-11-19 22:40:38
【问题描述】:

我有一些代码用于将数据行复制到您提供的对象中。数据行是弱类型的。现在,我可以使用反射将数据行中的所有数据分配给对象以获取属性,迭代这些属性并使用数据行设置它们的值。虽然这有效,但它仅在底层数据类型相同(没什么大不了)时才有效,更重要的是,只要属性和字段的顺序相同。

这个问题有一个警告。大约 90% 的列名与属性名匹配。这就是我挂断电话的地方。示例:在我返回数据行的数据库中,有一个名为 Date_Created 的字段,我的对象的属性在数据库中称为 Created_Date 或 Modified_By,在对象属性中称为 Update_By。 (我不能重命名属性或表,所以简单的答案是不可能的)。

我尝试这样做的原因是因为我的公司代码从数据库中获取数据返回弱类型数据集,当我们更新或向数据库添加数据时,我们必须填充一个自定义类并将其传递给更新过程.

我有什么方法可以比较数据行列并与对象属性进行比较或在运行时为数据行分配新的列名?

    private static T CopyRecord<T>(DataRow record, dynamic newRecord)
    {
        //Get Properties
        var properties = newRecord.GetType().GetProperties();
        var column = 0;
        foreach (PropertyInfo property in properties)
        {
            //If property is generic list, continue
            if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) continue;

            //Check for dbnull, return null if true, or convert to correct type
            var columnValue = Convert.IsDBNull(record[column]) ? null : Convert.ChangeType(record[column], Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType);

            //Set property for newRecord
            property.SetValue(newRecord, columnValue);
            column++;
        }
        return newRecord;
    }

编辑:在这种情况下使用自定义属性会起作用吗?我可以在我的类属性前面加上等效的数据库列名。这样,我可以在自定义类和弱类型数据行上使用反射并匹配所有数据。

【问题讨论】:

  • 请记住在您的标签中包含相关语言。
  • 我以为我有,但我将动态更改为运行时。

标签: c# object reflection copy runtime


【解决方案1】:

注意:永远不要像在这里那样使用位置参考!它要求讨厌的错误。当然,除非其他人会维护此代码,并且您计划到那时退出(这就是我认为我继承的代码发生的情况)。

属性

将属性放在属性上。阅读这些。

如果您无法控制泛型对象,但方法是可覆盖的,请从它继承。

映射

如果您不能这样做(或者这可能更容易),请将地图作为字典传递。现在,在不传递额外参数和锤击调用者的情况下轻松实现这并不是那么糟糕。继承对象并让它们实现一个返回映射的接口(或者如果您可以编辑原始对象,则直接实现)。

此接口上方法的实现(在您的特定对象中)将返回一个字典,其中包含映射。对于您的泛型方法,限制可以传递给它的类型。

那里有很多内容可以用谷歌搜索来充实“如何”……但我希望它能为您指明正确的方向。

【讨论】:

  • 是的,看起来它会让我朝着正确的方向前进。谢谢。今晚我会做一些研究,看看我能弄清楚什么。
  • +1 是的 - 我以前也被位置属性信息咬过:-)。但是,我不太喜欢使用额外的地图 - 还是您建议使用属性名称自动生成地图?
【解决方案2】:

一些注意事项:

  • newRecord 不应输入 dynamic。你知道这是一个T - 声明它。
  • 我强烈建议不要使用Convert - 我敢打赌你不理解它的语义(我确实试图避免知道所有奇怪的极端情况);即使你这样做了,盲目地转换类型通常也是隐藏错误的好方法。
  • 您正在按顺序匹配列 - 属性的顺序是未定义,并且在过去发生了变化。有一个未记录的解决方法;只要没有继承,您就可以按MetadataToken 排序并重新排序源顺序,但是为了正确性而依赖它确实是不可取的。一个更好的主意是按名称将列与属性匹配 - 您可以通过 record.Table.Columns 获取所有列。
  • 但是......在我看来,您真的在寻找micro-ORM。有很多非常优秀的可用,例如 PetaPocoDapper

微规则不会规定您使用 sql 的方式;它仅将 C# 对象映射到您从数据库中获取的行,反之亦然;这意味着它们比 LINQ 更灵活、更容易迁移,这也意味着 PetaPoco 和 Dapper 都比 LINQ 快得多,并且通常比手动编码更快,除非你真的注意正确使用低级 api。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-18
    • 2010-11-12
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多