由于传入对象可以是任意对象,不可能一一列举并特殊处理,所以乍一看,问题有些棘手,阅读了一些MS实践后找到了一个可以让更多类型的对象实现拷贝的方法,以下是思路:
- 如果传入对象是值类型,直接返回即可;这里可以通过Type.IsValueType来判断。
- 如果传入对象是IComponent,需要首先获取DesignHost,通过DesignHost创建IComponent的新实例,然后通过PropertyDescriptor对每个可以设置的属性做递归拷贝(由于代码量,这里没有列出对Component对象拷贝的代码)。
- 如果传入对象实现IClonable,采用Clone方式获得拷贝对象并返回。
- 获取传入对象的TypeConverter,尝试转换传入对象成InstanceDescriptor,如果传入对象允许转换成InstanceDescriptor,同时转换的InstanceDescriptor实例不为null,并且已经完成,调用InstanceDescriptor.Invoke获取拷贝对象。
- 如果3没有成功,如果传入对象允许转换成string并且允许从string转换成实例,尝试转换传入对象成string,在从string转换得出新对象。
- 如果4都失败了,检查传入对象的类型是否支持Serialize,通过Type.IsSerializable来判断;如果支持,首先Serialize传入对象到MemeryStream,然后通过Deserialize得到新对象并返回。
- 如果以上均失败,说明对象不支持Design-Time拷贝,直接返回。
1
private 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![](/Images/OutliningIndicators/InBlock.gif)
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
}
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/InBlock.gif)
7
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
8
![](/Images/OutliningIndicators/InBlock.gif)
9
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
10
![](/Images/OutliningIndicators/InBlock.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
16
![](/Images/OutliningIndicators/InBlock.gif)
17
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
20
![](/Images/OutliningIndicators/InBlock.gif)
21
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/InBlock.gif)
26
![](/Images/OutliningIndicators/InBlock.gif)
27
![](/Images/OutliningIndicators/InBlock.gif)
28
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
29
![](/Images/OutliningIndicators/InBlock.gif)
30
![](/Images/OutliningIndicators/InBlock.gif)
31
![](/Images/OutliningIndicators/InBlock.gif)
32
![](/Images/OutliningIndicators/InBlock.gif)
33
![](/Images/OutliningIndicators/InBlock.gif)
34
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](/Images/OutliningIndicators/InBlock.gif)
36
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
37
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
38
![](/Images/OutliningIndicators/InBlock.gif)
39
![](/Images/OutliningIndicators/InBlock.gif)
40
![](/Images/OutliningIndicators/InBlock.gif)
41
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
42
![](/Images/OutliningIndicators/InBlock.gif)
43
![](/Images/OutliningIndicators/InBlock.gif)
44
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
45
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
46
![](/Images/OutliningIndicators/InBlock.gif)
47
![](/Images/OutliningIndicators/InBlock.gif)
48
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
49
![](/Images/OutliningIndicators/InBlock.gif)
50
![](/Images/OutliningIndicators/InBlock.gif)
51
![](/Images/OutliningIndicators/InBlock.gif)
52
![](/Images/OutliningIndicators/InBlock.gif)
53
![](/Images/OutliningIndicators/InBlock.gif)
54
![](/Images/OutliningIndicators/InBlock.gif)
55
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
56
![](/Images/OutliningIndicators/InBlock.gif)
57
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
58
![](/Images/OutliningIndicators/InBlock.gif)
59
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
60
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
61
![](/Images/OutliningIndicators/InBlock.gif)
62
![](/Images/OutliningIndicators/InBlock.gif)
63
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)