如何“深度”克隆闭源第三方类的属性?

2024-02-13

The ICloneable http://msdn.microsoft.com/en-us/library/system.icloneable(v=vs.100).aspx.NET框架的接口通常提供一种方法来支持cloning http://en.wikipedia.org/wiki/Cloning_%28programming%29一个类的实例。

但如果我有多个第 3 方类,并且不想单独关心每个属性,如何有效地克隆这些类的对象? (这些类的源代码不可用)。 有没有办法使用generics http://msdn.microsoft.com/en-us/library/512aeb7t%28v=vs.100%29.aspx and 扩展方法 http://msdn.microsoft.com/en-us/library/vstudio/bb383977%28v=vs.100%29.aspx?

我需要的是一个深度克隆,它创建一个包含所有属性和(子)对象的精确副本。


Example:假设你想克隆一个UserQuery对象在LinqPad http://www.linqpad.net/:

void Main()
{
    UserQuery uc=this;
    var copy=uc.CreateCopy(); // clone it
}

我正在寻找的是CreateCopy()扩展允许创建副本而不必关心此类的详细信息,因为我不拥有该类的源UerQuery.

(注意UserQuery只是一个显示我需要的示例,它也可以是 PDF 文档类、用户控件类、ADO.NET 类或其他任何内容)。


我目前有2种不同的解决方案为此,一种使用反射,另一种不使用反射:


1.) With a 通用扩展方法 (plus 反射 http://msdn.microsoft.com/en-us/library/ms173183(v=vs.100).aspx)你可以在 C# 中这样做:

public static class Extension
{
    public static T CreateCopy<T>(this T src)
        where T: new()
    {
        if (src == null) return default(T); // just return null
        T tgt = new T(); // create new instance
        // then copy all properties
        foreach (var pS in src.GetType().GetProperties())
        {
            foreach (var pT in tgt.GetType().GetProperties())
            {
                if (pT.Name != pS.Name) continue;
                (pT.GetSetMethod()).Invoke(tgt, new object[] { 
                    pS.GetGetMethod().Invoke(src, null) });
            }
        };
        return tgt;
    } // method
} // class

这非常强大,因为现在您可以克隆每个对象,不仅仅是来自您编写的类的对象,而是来自所有类的对象包括系统类.NET 框架的。并且由于反思,你不需要知道它的属性,它们会被自动复制。

Example

使用方法CreateCopy(),假设你有一个Customer类和一个Order类,并且您需要使用新 ID 创建副本(不是引用)。然后您可以执行以下操作:

Order CopyOrderWithNewPK(Order item)
{
    Order newItem = item.CreateCopy(); // use ext. method to copy properties
    newItem.OrderId = new Guid(); // create new primary key for the item
    return newItem;
}

毫不奇怪,对于 Customer 类来说,它看起来是一样的:

Customer CopyCustomerWithNewPK(Customer item)
{
    Customer newItem = item.CreateCopy(); // use ext. method to copy properties
    newItem.CustomerId = new Guid(); // create new primary key for the item
    return newItem;
}

Note示例类中定义的所有属性的值都会自动复制。如果您不拥有源代码,您甚至可以克隆第 3 方程序集的对象。代价是反射方法速度较慢。


2.)还有另一种方法可以做到这一点没有反射,灵感来自于this https://stackoverflow.com/q/11599526/1016343问题。一个优点是它甚至能够克隆实体框架的对象(例如将实体对象附加和重新附加到不同的数据上下文):

// using System.Runtime.Serialization;
public class Cloner<T>
{
    readonly DataContractSerializer _serializer 
            = new DataContractSerializer(typeof(T));

    /// <summary>
    /// Clone an object graph
    /// </summary>
    /// <param name="graph"></param>
    /// <returns></returns>
    public T Clone(T graph)
    {
        MemoryStream stream = new MemoryStream();
        _serializer.WriteObject(stream, graph);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)_serializer.ReadObject(stream);
    }
}

为了不破坏上面的例子,你可以改变扩展方法CreateCopy如下:

public static class Extension
{   
    public static T CreateCopy<T>(this T src)
        where T: new()
    {
            return (new Cloner<T>()).Clone(src);
    }   
}   

Note:虽然Cloner正在使用System.Runtime.Serialization,被克隆的对象确实not需要可序列化。这可能是一个优势,我见过的其他解决方案只能克隆可序列化对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何“深度”克隆闭源第三方类的属性? 的相关文章

随机推荐

  • Express Handlebars 不会渲染数据

    我正在使用 Express Handlebars 模板引擎来使用 NodeJS 和 Express Handlebars 在尝试渲染模板时抛出以下错误 车把 访问已被拒绝解析属性 用户名 因为它不是其父级的 自己的财产 您可以添加一个 运行
  • 如何有条件地更新 panda 数据框中的多列

    我正在尝试有条件地更新我的熊猫数据框中的多行 这是我的数据 df pd DataFrame 1 1 1 2 2 2 3 3 3 columns list ABC 我可以通过两步完成我想要的更新 df loc df A 1 B df C 10
  • 如何在没有 setup.py 的情况下安装 Python 模块?

    我是 Python 新手 正在尝试安装此模块 http www catonmat net blog python library for google search http www catonmat net blog python lib
  • Boost Graph Library 多态捆绑属性

    所以我使用以下类型的增强图 typedef boost adjacency list
  • 将 Rails 引擎安装到生产中的多个应用程序的最佳实践

    我对在生产中组织 Rails 应用程序和可安装引擎有点困惑 我有 N 个应用程序 它们使用 1 个可安装引擎 它为应用程序设置一些 cookie 在开发中它是这样工作的 文件夹 app1 app2 my engine 在应用程序 Gemfi
  • 使用sycl在Windows上构建tensorflow c ++时未定义monolithic

    我正在尝试为在 GPU 上运行的 Windows 构建 TensorFlow C 或 TensorFlow lite 不使用 CUDA 它应该可以在 AMD 上运行 我最好的猜测是使用 OpenCL 和 SYCL 我下载了 Codeplay
  • 在 Zend Framework 1 中记录错误的最佳方法是什么?

    我们在 Zend Framework v1 中构建了一个应用程序 并且在设置错误报告和日志记录方面没有做太多工作 有没有什么方法可以让我们在不对代码进行太多更改的情况下获得某种级别或错误报告 有可用的 ErrorHandler 插件吗 基本
  • 继承React组件的正确方法

    我知道我的问题有点偏颇 但我对 Javascript 很陌生并且prototypes 我读过它 但我真的不明白如何将该技术应用于我的实际问题 所以一个例子会非常有帮助 所以我有一个React组件 基本上看起来像这样 var Componen
  • 当 HTTP POST 重定向到 GET 时,POST 正文会发生什么?

    按照我之前的question https stackoverflow com questions 4939195 redirecting an http post 我需要将 HTTP POST 请求重定向到不同的服务器 我相信这可以使用 p
  • java.lang.IllegalArgumentException:缺少某些字段(可选或强制)

    我正在尝试使用 Apache Camel Bindy 创建固定文件阅读器 但出现异常 请帮助我找到解决方案 没有页眉和页脚 效果很好 Update 文件很小 现在无法理解 并且添加了 public 文件内容 101 08 2009 30A9
  • 当我在 Grails 上调用 Post 方法时,params 为空

    我正在为我的应用程序编写网络服务 我的问题是 当我使用 GET 方法调用它时 它可以工作 但是当我使用 POST 方法时 params 不包含我的参数 当我使用 GET 调用时 这是 params 的内容 params username a
  • 如何重置 jquery 动画以重新开始?

    我已经构建了一段不错的代码 一些动画和一些单击 悬停事件 其中只有一小行 我打算在多个 html 文档上使用它 这是一个游戏 你必须得到正确的答案并继续下一个问题 用全页滑块构建在另一个 html 中 我不想加载 DOM 多个次 毫无意义
  • Java流减少

    我有以下示例数据集 我想使用基于方向值的 Java 流 api 对其进行转换 减少 Direction int IN 1 2 OUT 3 4 OUT 5 6 7 IN 8 IN 9 IN 10 11 OUT 12 13 IN 14 to D
  • 改造@GET - 如何显示请求字符串?

    我正在开发一个 Android 应用程序 它使用 Retrofit 创建一个安静的客户端 为了调试网络调用 我想显示或转储实际被调用的 url 有没有办法做到这一点 我在下面添加了一些代码 显示了应用程序当前如何使用改造 客户端接口定义 i
  • 如何在不停止 JVM 的情况下将 Javaagent 添加到 JVM?

    我希望在不停止应用程序的情况下分析 Java 应用程序 我可以在应用程序运行时以某种方式添加 Javaagent 吗 See 程序启动后启动Java代理 https stackoverflow com questions 1277219 s
  • JSON.NET:从 JProperty 值获取 JObject

    我被困在某件事上 我使用 JObject Load 反序列化了一个 JSON 文件 get the JSON into an object JObject jsonObject JObject Load new JsonTextReader
  • 运行不带参数或任务名称的 CLI Thor 应用程序

    我正在寻找一种方法来创建一个命令行雷神应用程序 该应用程序将运行不带任何参数的默认方法 我摆弄了 Thor 的 default method 选项 但仍然要求我传递一个参数 我找到了一个类似案例 https stackoverflow co
  • 计算文本区域字符数

    我正在为我的文本区域开发字符计数website http ilanshomekitchen x10 mx new contact html 现在显示NaN 因为它似乎没有找到该字段中有多少个字符的长度 该字段一开始是0 所以数字应该是500
  • NHibernate (+ FluentNhibernate) : 连接两个独立的表

    我在创建具有共同属性的两个实体的联接时遇到问题 但它们没有映射在一起 假设您有一个实体 Article 其中包含属性 FamilyCode 和一个具有属性 Code 和 Label 的实体 Family 在我的映射中 Article 没有引
  • 如何“深度”克隆闭源第三方类的属性?

    The ICloneable http msdn microsoft com en us library system icloneable v vs 100 aspx NET框架的接口通常提供一种方法来支持cloning http en