UIElement
を2 つの異なるキャンバスに追加する必要がありますが、一方は 1 つのキャンバスUIElement
の子にしかできないため、の ShallowCopy (DeepCopy は不要) を作成する必要がありUIElement
ます。
を使いたい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);
}