4

我正在尝试在 C# 中创建剪贴板堆栈。剪贴板数据存储在System.Windows.Forms.DataObject对象中。我想将每个剪贴板条目 ( IDataObject) 直接存储在通用列表中。由于位图(似乎)的存储方式,我认为我需要先执行深层复制,然后再将其添加到列表中。

我尝试使用二进制序列化(见下文)来创建深层副本,但由于System.Windows.Forms.DataObject未标记为可序列化,因此序列化步骤失败。有任何想法吗?

public IDataObject GetClipboardData()
{
    MemoryStream memoryStream = new MemoryStream();
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(memoryStream, Clipboard.GetDataObject());
    memoryStream.Position = 0;
    return (IDataObject) binaryFormatter.Deserialize(memoryStream);
}
4

3 回答 3

3

我为另一个问题编写了下面的代码,也许在这种情况下它可能对您有用:

    public static class GhettoSerializer
    {
            // you could make this a factory method if your type
            // has a constructor that appeals to you (i.e. default 
            // parameterless constructor)
            public static void Initialize<T>(T instance, IDictionary<string, object> values)
            {
                    var props = typeof(T).GetProperties();

                    // my approach does nothing to handle rare properties with array indexers
                    var matches = props.Join(
                            values,
                            pi => pi.Name,
                            kvp => kvp.Key,
                            (property, kvp) =>
                                    new {
                                            Set = new Action<object,object,object[]>(property.SetValue), 
                                            kvp.Value
                                    }
                    );

                    foreach (var match in matches)
                            match.Set(instance, match.Value, null);
            }
            public static IDictionary<string, object> Serialize<T>(T instance)
            {
                    var props = typeof(T).GetProperties();

                    var ret = new Dictionary<string, object>();

                    foreach (var property in props)
                    {
                            if (!property.CanWrite || !property.CanRead)
                                    continue;
                            ret.Add(property.Name, property.GetValue(instance, null));
                    }

                    return ret;
            }
    }

但是,我认为这不会是您问题的最终解决方案,尽管它可能会给您一个起点。

于 2008-10-14T17:09:38.450 回答
0

查找 Serializable 的扩展坞并找到有关序列化助手的内容。您可以将位图包装在您自己的与 .net 框架集成的序列化代码中。

于 2009-01-05T04:56:01.467 回答
0

我的答案副本:.net 中 DataContract 属性和 Serializable 属性之间的区别

我的回答在这里比那里好得多,尽管上面的问题以:

“......或者也许是创建深度克隆的不同方式?”

我曾经通过反射对对象结构进行了一些检查,以找到反序列化所需的所有程序集,并将它们与引导程序一起序列化。

通过一些工作,您可以构建一种类似的深度复制方法。基本上,您需要一个带有 Dictionary 的递归方法来检测循环引用。在方法中,您检查所有字段,如下所示:

private void InspectRecursively(object input,
    Dictionary<object, bool> processedObjects)
{
  if ((input != null) && !processedObjects.ContainsKey(input))
  {
    processedObjects.Add(input, true);

    List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
        BindingFlags.Public | BindingFlags.NonPublic );
    foreach (FieldInfo field in fields)
    {
      object nextInput = field.GetValue(input);

      if (nextInput is System.Collections.IEnumerable)
      {
        System.Collections.IEnumerator enumerator = (nextInput as
            System.Collections.IEnumerable).GetEnumerator();

        while (enumerator.MoveNext())
        {
          InspectRecursively(enumerator.Current, processedObjects);
        }
      }
      else
      {
        InspectRecursively(nextInput, processedObjects);
      }
    }
  }
}

为了让它工作,你需要添加一个输出对象和类似的东西System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type)来创建每个字段值的最浅的副本(即使没有复制引用)。最后,您可以使用类似的内容设置每个字段field.SetValue(input, output)

但是,此实现不支持已注册的事件处理程序,反序列化也_un_支持。此外,层次结构中的每个对象都将被破坏,如果其类的构造函数需要初始化任何内容而不是设置所有字段。最后一点仅适用于序列化,如果该类具有相应的实现,例如方法标记[OnDeserialized],实现ISerializable,...。

于 2013-11-07T13:18:15.303 回答