Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Silverlight4深度复制可视元素_Silverlight_Clone_Uielement - Fatal编程技术网

Silverlight4深度复制可视元素

Silverlight4深度复制可视元素,silverlight,clone,uielement,Silverlight,Clone,Uielement,我有一个自定义的视觉元素,我想在silverlight应用程序中创建一个深度副本 我尝试了很多方法,但没有找到任何解决方法。。。 这里是我找到的最好的解决方案,但是原始的DeviceControl和副本是链接的。 如果我更改其中一个的属性,则第二个属性也会更改。我要他们独立 你有主意了吗 void CloneDevice() { DeviceControl control = this; DeviceControl copy = CloneObject.DeepClone<DeviceC

我有一个自定义的视觉元素,我想在silverlight应用程序中创建一个深度副本

我尝试了很多方法,但没有找到任何解决方法。。。 这里是我找到的最好的解决方案,但是原始的DeviceControl和副本是链接的。 如果我更改其中一个的属性,则第二个属性也会更改。我要他们独立

你有主意了吗

void CloneDevice()
{
DeviceControl control = this; 
DeviceControl copy = CloneObject.DeepClone<DeviceControl>(control);
ExtensionMethods.DeepCopy(control, copy);
}

//[Obfuscation(Exclude = true)]
    internal static class CloneObject
    {
        private static bool _firstTry = false;

        private static List<FieldInfo> _attachedProperties = null;

        // Extension for any class object
        internal static TT DeepClone<TT>(this TT source, bool?cloneAttachedProperties  = null)
        { // Jim McCurdy's DeepClone
            if (cloneAttachedProperties == null)
                cloneAttachedProperties = (source is DependencyObject);

            // The first time this method is called, compute a list of all
            // attached properties that exist in this XAP's assemblies
            if (cloneAttachedProperties == true && _attachedProperties == null)
            {
                _attachedProperties = new List<FieldInfo>();
                List<Assembly> assemblies = GetLoadedAssemblies();
                foreach (Assembly assembly in assemblies)
                    GetAttachedProperties(_attachedProperties, assembly);
            }

            TT clone = CloneRecursive(source);

            if (clone is FrameworkElement)
            {
                FrameworkElement cloneElement = (clone as FrameworkElement);
                cloneElement.Arrange(new Rect(0, 0, cloneElement.ActualWidth, cloneElement.ActualHeight));
            }

            return clone;
        }

        private static TT CloneRecursive<TT>(TT source)
        {
            if (source == null || source.GetType().IsValueType)
                return source;

            // Common types that do not have parameterless constructors
            if (source is string || source is Type || source is Uri || source is DependencyProperty)
                return source;

            TT clone = CloneCreate(source);
            if (clone == null)
                return source;

            if (source is IList)
                CloneList(source as IList, clone as IList);

            //CloneProperties(source, clone);//ca plante si on prend les propriétées comme ca

            return clone;
        }

        private static TT CloneCreate<TT>(TT source)
        {
            try
            {
#if DEBUG_TRACE
            string.Format("Clone create object Type={0}", SimpleType(source.GetType())).Trace();
#endif
                Array sourceArray = (source as Array);
                if (sourceArray == null)
                    return (TT)Activator.CreateInstance(source.GetType());
                if (sourceArray.Rank == 1)
                    return (TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
                        sourceArray.GetLength(0));
                if (sourceArray.Rank == 2)
                    return (TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
                        sourceArray.GetLength(0), sourceArray.GetLength(1));
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("No parameterless constructor"))
                    return default(TT);
                //string.Format("Can't create object Type={0}", SimpleType(source.GetType())).Trace();
                //ex.DebugOutput();
            }

            return default(TT);
        }

        private static void CloneProperties(object source, object clone)
        {
            // The binding flags indicate what properties we will clone
            // Unfortunately, we cannot clone "internal" or "protected" properties
            BindingFlags flags =
                BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public;

            if (source is DependencyObject)
            {
                DependencyObject sourcedp = source as DependencyObject;
                DependencyObject clonedp = clone as DependencyObject;

                // Clone attached properties
                if (_attachedProperties != null && _attachedProperties.Count > 0)
                    foreach (FieldInfo field in _attachedProperties)
                        CloneDependencyProperty(sourcedp, clonedp, field, true);

                // Clone dependency properties
                FieldInfo[] fields = source.GetType().GetFields(flags | BindingFlags.Static);
                foreach (FieldInfo field in fields)
                    CloneDependencyProperty(sourcedp, clonedp, field, false);
            }

            // Clone CLR properties
            if (source is DeviceControl && _firstTry == false)
            {
                _firstTry = true;
                PropertyInfo[] properties = source.GetType().GetProperties(flags);
                foreach (PropertyInfo property in properties)
                    CloneProperty(source, clone, property);
            }
        }

        private static void CloneDependencyProperty(DependencyObject sourceObject,
            DependencyObject cloneObject, FieldInfo field, bool isAttached)
        {
            try
            {
                // Blacklisted properties that can't (or shouldn't) be set
                if (field.Name == "NameProperty" && sourceObject is FrameworkElement) return;

                DependencyProperty dp = field.GetValue(sourceObject) as DependencyProperty;
                if (dp == null) // Event DependencyProperties will be null
                    return;

                object sourceValue = null;
                try
                {
                    sourceValue = sourceObject.GetValue(dp);
                }
                catch (Exception)
                {
                }

                if (sourceValue == null)
                    return;
                // Don't set attached properties if we don't have to
                if (isAttached)
                {
                    Type sourceType = sourceValue.GetType();
                    if (sourceType.IsValueType && sourceValue.Equals(Activator.CreateInstance(sourceType)))
                        return;
                }
#if DEBUG_TRACE
            string.Format("Clone dependency property Name={0}, Value={2} for source Type={1}",
                field.Name, SimpleType(sourceObject.GetType()), sourceValue).Trace();
#endif
                // Blacklisted properties that can't (or don't need to be) cloned
                bool doClone = true;
                if (field.Name == "DataContextProperty") doClone = false;
                //if (field.Name == "TargetPropertyProperty") doClone = false;

                object cloneValue = (doClone ? CloneRecursive(sourceValue) : sourceValue);
                cloneObject.SetValue(dp, cloneValue);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("read-only"))
                    return;
                if (ex.Message.Contains("read only"))
                    return;
                if (ex.Message.Contains("does not fall within the expected range"))
                    return;
                //string.Format("Can't clone dependency property Name={0}, for source Type={1}",
                //    field.Name, SimpleType(sourceObject.GetType())).Trace();
                //ex.DebugOutput();
            }
        }

        private static void CloneProperty(object source, object clone, PropertyInfo property)
        {
            try
            {
                if (!property.CanRead || !property.CanWrite || property.GetIndexParameters().Length != 0)
                    return;

                // Blacklisted properties that can't (or shouldn't) be set
                if (property.Name == "Name" && source is FrameworkElement) return;
                if (property.Name == "InputScope" && source is TextBox) return; // Can't get
                if (property.Name == "Watermark" && source is TextBox) return; // Can't get
                if (property.Name == "Source" && source is ResourceDictionary) return; // Can't set
                if (property.Name == "TargetType" && source is ControlTemplate) return; // Can't set

                bool publicSetter = (source.GetType().GetMethod("set_" + property.Name) != null);
                bool isList = (property.PropertyType.GetInterface("IList", true) != null);
                if (!publicSetter && !isList)
                    return;

                object sourceValue = property.GetValue(source, null);
                if (sourceValue == null)
                    return;

                if (!publicSetter && isList)
                {
                    IList cloneList = property.GetValue(clone, null) as IList;
                    if (cloneList != null)
                        CloneList(sourceValue as IList, cloneList);
                    return;
                }
#if DEBUG_TRACE
            string.Format("Clone property Type={0}, Name={1}, Value={3} for source Type={2}",
                SimpleType(property.PropertyType), property.Name, SimpleType(source.GetType()),
                sourceValue).Trace();
#endif
                // Blacklisted properties that can't (or don't need to be) cloned
                bool doClone = true;
                if (source is FrameworkElement && property.Name == "DataContext") doClone = false;
                //if (property.Name == "TargetProperty") doClone = false;

                object cloneValue = (doClone ? CloneRecursive(sourceValue) : sourceValue);
                property.SetValue(clone, cloneValue, null); // possible MethodAccessException
            }
            catch (Exception ex)
            {
                //string.Format("Can't clone property Type={0}, Name={1}, for source Type={2}",
                //    SimpleType(property.PropertyType), property.Name, SimpleType(source.GetType())).Trace();
                //ex.DebugOutput();
            }
        }

        private static void CloneList(IList sourceList, IList cloneList)
        {
            try
            {
                IEnumerator sourceEnumerator = sourceList.GetEnumerator();
                Array sourceArray = sourceList as Array;
                Array cloneArray = cloneList as Array;
                int dim0 = (sourceArray != null && sourceArray.Rank > 0 ? sourceArray.GetLowerBound(0) : 0);
                int dim1 = (sourceArray != null && sourceArray.Rank > 1 ? sourceArray.GetLowerBound(1) : 0);

                while (sourceEnumerator.MoveNext())
                {
                    object sourceValue = sourceEnumerator.Current;
#if DEBUG_TRACE
                string.Format("Clone IList item {0}", sourceValue).Trace();
#endif
                    object cloneValue = CloneRecursive(sourceValue);
                    if (sourceArray == null)
                        cloneList.Add(cloneValue);
                    else
                        if (sourceArray.Rank == 1)
                            cloneArray.SetValue(cloneValue, dim0++);
                        else
                            if (sourceArray.Rank == 2)
                            {
                                cloneArray.SetValue(cloneValue, dim0, dim1);
                                if (++dim1 > sourceArray.GetUpperBound(1))
                                {
                                    dim1 = sourceArray.GetLowerBound(1);
                                    if (++dim0 > sourceArray.GetUpperBound(0))
                                        dim0 = sourceArray.GetLowerBound(0);
                                }
                            }
                }
            }
            catch (Exception ex)
            {
                //string.Format("Can't clone IList item Type={0}", SimpleType(sourceList.GetType())).Trace();
                //ex.DebugOutput();
            }
        }

        private static string SimpleType(Type type)
        {
            string typeName = type.ToString();
            int index = typeName.LastIndexOf('[');
            if (index < 0)
                return typeName.Substring(typeName.LastIndexOf('.') + 1);

            string collectionName = typeName.Substring(index);
            collectionName = collectionName.Substring(collectionName.LastIndexOf('.') + 1);
            typeName = typeName.Substring(0, index);
            typeName = typeName.Substring(typeName.LastIndexOf('.') + 1);
            return typeName + '[' + collectionName;
        }

        private static List<Assembly> GetLoadedAssemblies()
        {
            List<Assembly> assemblies = new List<Assembly>();

            foreach (AssemblyPart part in Deployment.Current.Parts)
            {
                StreamResourceInfo sri =
                    Application.GetResourceStream(new Uri(part.Source, UriKind.Relative));
                if (sri == null)
                    continue;
                Assembly assembly = new AssemblyPart().Load(sri.Stream);
                if (assembly != null && !assemblies.Contains(assembly))
                    assemblies.Add(assembly);
            }

            // Additional assemblies that are not found when examining of Deployment.Current.Parts above
            Type[] types =
        {
            typeof(System.Windows.Application), // System.Windows.dll,
            #if INCLUDE_ASSEMBLIES_WITHOUT_ATTACHED_PROPERTIES
            typeof(System.Action), // mscorlib.dll,
            typeof(System.Uri), // System.dll,
            typeof(System.Lazy<int>), // System.Core.dll,
            typeof(System.Net.Cookie), // System.Net.dll,
            typeof(System.Runtime.Serialization.StreamingContext), // System.Runtime.Serialization.dll,
            typeof(System.ServiceModel.XmlSerializerFormatAttribute), // System.ServiceModel.dll,
            typeof(System.Windows.Browser.BrowserInformation), // System.Windows.Browser.dll,
            typeof(System.Xml.ConformanceLevel), // System.Xml.dll,
            #endif
        };

            foreach (Type type in types)
            {
                Assembly assembly = type.Assembly;
                if (assembly != null && !assemblies.Contains(assembly))
                    assemblies.Add(assembly);
            }

            return assemblies;
        }

        private static bool GetAttachedProperties(List<FieldInfo> attachedProperties, Assembly assembly)
        {
            BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static;
            foreach (Type type in assembly.GetTypes())
            {
                FieldInfo[] fields = type.GetFields(flags);
                MethodInfo[] methods = null;
                foreach (FieldInfo field in fields)
                {
                    if (field.FieldType==(typeof(DependencyProperty)))
                        continue;
                    if (!field.Name.EndsWith("Property"))
                        continue;

                    string fieldName = field.Name.Replace("Property", "");
                    string getName = "Get" + fieldName;
                    string setName = "Set" + fieldName;
                    bool foundGet = false;
                    bool foundSet = false;
                    if (methods == null)
                        methods = type.GetMethods(flags);
                    foreach (MethodInfo method in methods)
                    {
                        if (method.Name == getName && method.GetParameters().Length == 1 &&
                            method.GetParameters()[0].ParameterType== (typeof(DependencyObject)))
                            foundGet = true;
                        else
                            if (method.Name == setName && method.GetParameters().Length == 2 &&
                                method.GetParameters()[0].ParameterType==(typeof(DependencyObject)))
                                foundSet = true;
                        if (foundGet && foundSet)
                            break;
                    }

                    if (!(foundGet && foundSet))
                        continue;

                    try
                    {
                        DependencyProperty dp = field.GetValue(null) as DependencyProperty;
                    }
                    catch (Exception)
                    {
                        continue;
                    }

                    // Found an attached Dependency Property
                    attachedProperties.Add(field);
                }
            }

            return true;
        }
    }

public static void DeepCopy(object source, object destination)
        {
            // Get properties
            var propertyInfos = source.GetType().GetProperties();
            // Evaluate
            if (propertyInfos.Length > 0)
            {
                foreach (var propInfo in propertyInfos)
                {
                    // Process only public properties
                    if (propInfo.CanWrite)
                    {
                        if (propInfo.Name == "IsSelected")
                        {
                            break;
                        }
                        else
                        {
                            object value = propInfo.GetValue(source, null);
                            propInfo.SetValue(destination, value, null);

                            // Evaluate
                            if (value != null)
                            {
                                var newPropInfo = value.GetType().GetProperties();
                                if (newPropInfo.Length > 0)
                                {
                                    // Copy properties for each child where necessary
                                    DeepCopy(
                                        source.GetType().GetProperty(propInfo.Name),
                                        destination.GetType().GetProperty(propInfo.Name));
                                }
                            }
                        }
                    }
                }
            }
        }
void CloneDevice()
{
设备控制=此;
DeviceControl copy=CloneObject.DeepClone(控制);
DeepCopy(控制,复制);
}
//[混淆(排除=真)]
内部静态类CloneObject
{
私有静态bool_firstTry=false;
私有静态列表_attachedProperties=null;
//任何类对象的扩展
内部静态TT DeepClone(此TT源,bool?cloneAttachedProperties=null)
{//Jim McCurdy的深度克隆
if(cloneAttachedProperties==null)
cloneAttachedProperties=(源是DependencyObject);
//第一次调用此方法时,计算所有
//此XAP程序集中存在的附加属性
if(cloneAttachedProperties==true&&u attachedProperties==null)
{
_attachedProperties=新列表();
列表程序集=GetLoadedAssemblies();
foreach(部件中的部件)
GetAttachedProperties(_attachedProperties,assembly);
}
TT clone=CloneRecursive(来源);
如果(克隆是FrameworkElement)
{
FrameworkElement cloneElement=(克隆为FrameworkElement);
cloneElement.Arrange(新的Rect(0,0,cloneElement.ActualWidth,cloneElement.ActualHeight));
}
返回克隆;
}
专用静态TT CloneRecursive(TT源)
{
if(source==null | | source.GetType().IsValueType)
返回源;
//没有无参数构造函数的常见类型
if(源为字符串| |源为类型| |源为Uri | |源为DependencyProperty)
返回源;
TT克隆=克隆创建(源);
如果(克隆==null)
返回源;
如果(源为IList)
克隆列表(源为IList,克隆为IList);
//克隆属性(来源,克隆);//可以种植在普通植物上
返回克隆;
}
专用静态TT克隆创建(TT源)
{
尝试
{
#如果调试跟踪
Format(“克隆创建对象类型={0}”,SimpleType(source.GetType())).Trace();
#恩迪夫
数组sourceArray=(源作为数组);
if(sourceArray==null)
return(TT)Activator.CreateInstance(source.GetType());
if(sourceArray.Rank==1)
return(TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
GetLength(0));
if(sourceArray.Rank==2)
return(TT)(object)Array.CreateInstance(source.GetType().GetElementType(),
sourceArray.GetLength(0),sourceArray.GetLength(1));
}
捕获(例外情况除外)
{
if(例如Message.Contains(“无参数构造函数”))
返回默认值(TT);
//Format(“无法创建对象类型={0}”),SimpleType(source.GetType()).Trace();
//例如DebugOutput();
}
返回默认值(TT);
}
专用静态void克隆属性(对象源、对象克隆)
{
//绑定标志指示我们将克隆哪些属性
//不幸的是,我们无法克隆“内部”或“受保护”属性
绑定标志=
BindingFlags.Instance | BindingFlags.FlatterHierarchy | BindingFlags.Public;
如果(源是DependencyObject)
{
DependencyObject sourcedp=源作为DependencyObject;
DependencyObject clonedp=克隆为DependencyObject;
//克隆附加属性
如果(_attachedProperties!=null&&u attachedProperties.Count>0)
foreach(附件属性中的FieldInfo字段)
CloneDependencyProperty(sourcedp,clonedp,field,true);
//克隆依赖项属性
FieldInfo[]fields=source.GetType().GetFields(标志| BindingFlags.Static);
foreach(字段中的字段信息字段)
CloneDependencyProperty(sourcedp,clonedp,field,false);
}
//克隆CLR属性
if(源为DeviceControl&&&u firstTry==false)
{
_firstTry=true;
PropertyInfo[]properties=source.GetType().GetProperties(标志);
foreach(属性中的PropertyInfo属性)
克隆属性(源、克隆、属性);
}
}
私有静态void CloneDependencyProperty(DependencyObject sourceObject,
DependencyObject克隆对象,FieldInfo字段,布尔值已附加)
{
尝试
{
//无法(或不应该)设置的黑名单属性
if(field.Name==“NameProperty”&&sourceObject为FrameworkElement)返回;
DependencyProperty dp=field.GetValue(sourceObject)作为DependencyProperty;
if(dp==null)//事件相关属性将为null
返回;
对象sourceValue=null;
尝试
{
sourceValue=sourceObject.GetValue(dp);
}
捕获(例外)
{
void CloneDevice()
{
    DeviceControl control = this; 
    string json = JsonConvert.SerializeObject(control, Formatting.Indented);
    DeviceControl copy = (DeviceControl)JsonConvert.DeserializeObject(json, this.GetType());
}