zoukankan      html  css  js  c++  java
  • How to copy object at DesignTime?

        在Review项目时发现有个Design-Time Feature,要求实现对任意Object实现拷贝,使得Run起来之后是两个独立对象,看了code,发现只能对IComponent、IClonable对象做拷贝,其他的就只能算Limitation了,于是自己研究了一下,结合MS的实践,设计了个新的实现
        由于传入对象可以是任意对象,不可能一一列举并特殊处理,所以乍一看,问题有些棘手,阅读了一些MS实践后找到了一个可以让更多类型的对象实现拷贝的方法,以下是思路:
    1. 如果传入对象是值类型,直接返回即可;这里可以通过Type.IsValueType来判断。
    2. 如果传入对象是IComponent,需要首先获取DesignHost,通过DesignHost创建IComponent的新实例,然后通过PropertyDescriptor对每个可以设置的属性做递归拷贝(由于代码量,这里没有列出对Component对象拷贝的代码)。
    3. 如果传入对象实现IClonable,采用Clone方式获得拷贝对象并返回。
    4. 获取传入对象的TypeConverter,尝试转换传入对象成InstanceDescriptor,如果传入对象允许转换成InstanceDescriptor,同时转换的InstanceDescriptor实例不为null,并且已经完成,调用InstanceDescriptor.Invoke获取拷贝对象。
    5. 如果3没有成功,如果传入对象允许转换成string并且允许从string转换成实例,尝试转换传入对象成string,在从string转换得出新对象。
    6. 如果4都失败了,检查传入对象的类型是否支持Serialize,通过Type.IsSerializable来判断;如果支持,首先Serialize传入对象到MemeryStream,然后通过Deserialize得到新对象并返回。
    7. 如果以上均失败,说明对象不支持Design-Time拷贝,直接返回。
        以下是实现:
     1private static object CopyValue(object value)
     2{
     3    if (value != null)
     4    {
     5        Type theTypeOfValue = value.GetType();
     6        if (theTypeOfValue.IsValueType) // If the value is ValueType, return value is just the copy.
     7        {
     8            return value;
     9        }

    10
    11        object newValue = null;
    12        if (value is IComponent)
    13        // If the value is IComponent, use DesignHost to create a new Component instance, and copy
    14        // all properties from value to new Component instance, here CopyComponent is the entrance.
    15        {
    16            newVlaue = CopyComponent(value as IComponent);
    17        }

    18        if (newValue == null && value is ICloneable) // If the value is Cloneable, call IClone.Clone to clone object.
    19        {
    20            newValue = (value as ICloneable).Clone();
    21        }

    22        if (newValue == null)
    23        {
    24            TypeConverter theConverterOfValueObject = TypeDescriptor.GetConverter(value);
    25            // If the value have a TypeConverter, try use TypeConverter to convert the object
    26            // to InstanceDescriptor, if convert successfully, the new value is just copied one.
    27            if (theConverterOfValueObject.CanConvertTo(typeof(InstanceDescriptor)))
    28            {
    29                InstanceDescriptor id = (InstanceDescriptor)theConverterOfValueObject.ConvertTo(null,
    30                    System.Globalization.CultureInfo.InvariantCulture,
    31                    value,
    32                    typeof(InstanceDescriptor));
    33                if ((id != null&& id.IsComplete)
    34                {
    35                    newValue = id.Invoke();
    36                }

    37            }

    38            // if above convert failed, try convert the object to string.
    39            if (((newValue == null&& theConverterOfValueObject.CanConvertTo(typeof(string)))
    40                && theConverterOfValueObject.CanConvertFrom(typeof(string)))
    41            {
    42                object convertedObject = theConverterOfValueObject.ConvertToInvariantString(value);
    43                newValue = theConverterOfValueObject.ConvertFromInvariantString((string)convertedObject);
    44            }

    45        }

    46        // Above copy failed, try use Serialize.
    47        if ((newValue == null&& theTypeOfValue.IsSerializable)
    48        {
    49            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf 
    50                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    51            MemoryStream ms = new MemoryStream();
    52            bf.Serialize(ms, value);
    53            ms.Position = 0;
    54            newValue = bf.Deserialize(ms);
    55        }

    56        if (newValue != null)
    57        {
    58            return newValue;
    59        }

    60    }

    61    // Can not copy the object, return original object.
    62    return value;
    63}

    To be the apostrophe which changed “Impossible” into “I’m possible”
    ----------------------------------------------------
    WinkingZhang's Blog (http://winkingzhang.cnblogs.com)
    GCDN(http://gcdn.grapecity.com/cs)
  • 相关阅读:
    nginx (待更新)
    根据 thread id 停止一个线程
    Redis 消息订阅
    faker smtp server
    DRF lazy Serializer
    python super
    django patch
    django patch 解决 ["'15428560000' value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."]
    自己的随笔
    CSS中文乱码解决方法
  • 原文地址:https://www.cnblogs.com/winkingzhang/p/1036489.html
Copyright © 2011-2022 走看看