1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Globalization;
6 
7 namespace System.ComponentModel
8 {
9     /// <summary>
10     /// <para>Provides a type converter to convert <see cref='System.Array'/>
11     /// objects to and from various other representations.</para>
12     /// </summary>
13     public class ArrayConverter : CollectionConverter
14     {
15         /// <summary>
16         ///    <para>Converts the given value object to the specified destination type.</para>
17         /// </summary>
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)18         public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
19         {
20             if (destinationType == null)
21             {
22                 throw new ArgumentNullException(nameof(destinationType));
23             }
24 
25             if (destinationType == typeof(string) && value is Array)
26             {
27                 return SR.Format(SR.Array, value.GetType().Name);
28             }
29 
30             return base.ConvertTo(context, culture, value, destinationType);
31         }
32 
33         /// <summary>
34         ///    <para>Gets a collection of properties for the type of array specified by the value parameter.</para>
35         /// </summary>
GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)36         public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
37         {
38             if (value == null)
39             {
40                 return null;
41             }
42 
43             PropertyDescriptor[] props = null;
44 
45             if (value.GetType().IsArray)
46             {
47                 Array valueArray = (Array)value;
48                 int length = valueArray.GetLength(0);
49                 props = new PropertyDescriptor[length];
50 
51                 Type arrayType = value.GetType();
52                 Type elementType = arrayType.GetElementType();
53 
54                 for (int i = 0; i < length; i++)
55                 {
56                     props[i] = new ArrayPropertyDescriptor(arrayType, elementType, i);
57                 }
58             }
59 
60             return new PropertyDescriptorCollection(props);
61         }
62 
63         /// <summary>
64         ///    <para>Gets a value indicating whether this object supports properties.</para>
65         /// </summary>
GetPropertiesSupported(ITypeDescriptorContext context)66         public override bool GetPropertiesSupported(ITypeDescriptorContext context)
67         {
68             return true;
69         }
70 
71         private class ArrayPropertyDescriptor : SimplePropertyDescriptor
72         {
73             private readonly int _index;
74 
ArrayPropertyDescriptor(Type arrayType, Type elementType, int index)75             public ArrayPropertyDescriptor(Type arrayType, Type elementType, int index)
76                 : base(arrayType, "[" + index + "]", elementType, null)
77             {
78                 _index = index;
79             }
80 
GetValue(object instance)81             public override object GetValue(object instance)
82             {
83                 var array = instance as Array;
84                 if (array != null && array.GetLength(0) > _index)
85                 {
86                     return array.GetValue(_index);
87                 }
88 
89                 return null;
90             }
91 
SetValue(object instance, object value)92             public override void SetValue(object instance, object value)
93             {
94                 if (instance is Array)
95                 {
96                     Array array = (Array)instance;
97                     if (array.GetLength(0) > _index)
98                     {
99                         array.SetValue(value, _index);
100                     }
101 
102                     OnValueChanged(instance, EventArgs.Empty);
103                 }
104             }
105         }
106     }
107 }
108