【发布时间】:2012-11-23 01:10:09
【问题描述】:
我需要将UIElement 添加到两个不同的画布,但一个UIElement 只能是一个画布的子级,因此我必须创建UIElement 的ShallowCopy(不需要DeepCopy)。
我想使用MemberwiseClone,但它受到保护,我不能使用它。
我也想定义一个扩展方法UIElement.ShallowCopy,但是还是调用MemberwiseClone,又被保护了。
编辑:
尝试了以下所有方法,但在 Silverlight 环境中均失败:
// System.Runtime.Serialization.InvalidDataContractException was unhandled by user code
// Message=Type 'System.Windows.UIElement' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.
public static T CloneEx<T>(this T obj) where T : class
{
T clone;
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
dcs.WriteObject(ms, obj);
ms.Position = 0;
clone = (T)dcs.ReadObject(ms);
}
return clone;
}
// This one also throws Access/Invoke exceptions
private readonly static object _lock = new object();
public static T MemberwiseCloneEx<T>(this T obj) where T : class
{
if (obj == null)
return null;
try
{
Monitor.Enter(_lock);
T clone = (T)Activator.CreateInstance(obj.GetType());
PropertyInfo[] fields = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (PropertyInfo field in fields)
{
object val = field.GetValue(obj, null);
field.SetValue(clone, val, null);
}
return clone;
}
finally
{
Monitor.Exit(_lock);
}
}
// System.MethodAccessException was unhandled by user code
// Message=Attempt by method 'ToonController.ControllerUtils.MemberwiseCloneEx<System.__Canon>(System.__Canon)' to access method 'System.Object.MemberwiseClone()' failed.
public static T MemberwiseCloneEx<T>(this T obj) where T : class
{
if (obj == null)
return null;
MethodInfo mi = obj.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
if (mi == null)
return null;
return (T)mi.Invoke(obj, null);
}
【问题讨论】:
-
你不能克隆一个对象,除非它被设计成可克隆的。您需要自己复制。
标签: silverlight clone uielement shallow-copy