我正在尝试在C#中创建一个剪贴板堆栈。剪贴板数据存储在System.Windows.Forms.DataObject
个对象中。我想将每个剪贴板条目(IDataObject
)直接存储在通用列表中。由于Bitmaps(似乎是)存储的方式,我认为在将其添加到列表之前我需要先执行深层复制。
我尝试使用二进制序列化(见下文)来创建深层副本,但由于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);
}
答案 0 :(得分: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;
}
}
但是我不认为这将是你问题的最终解决方案,虽然它可能会给你一个开始的地方。
答案 1 :(得分:0)
查找Serializable的Dock,找到有关序列化助手的内容。您可以将位图包装在您自己的序列化代码中,并与.net框架集成。
答案 2 :(得分:0)
将我的答案复制到:difference between DataContract attribute and Serializable attribute in .net
我的回答比这里好得多,尽管上面的问题以:
结束&#34; ...或者可能是另一种创建深层克隆的方式?&#34;
我曾经通过Reflection对对象结构进行了一些检查,以找到反序列化所需的所有程序集,并将它们串行化以进行自举。
通过一些工作,可以构建类似的深度复制方法。基本上你需要一个递归方法,沿着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 _。此外,层次结构中的每个对象都将被破坏,如果它的类别为&#39;构造函数需要初始化任何东西,但设置所有字段。最后一点仅适用于序列化,如果该类具有相应的实现,例如标记为[OnDeserialized]
的方法,实现ISerializable
,....