Initial commit
[mono.git] / mcs / class / referencesource / System / compmod / system / componentmodel / ReferenceConverter.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ReferenceConverter.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 /*
8  */
9 namespace System.ComponentModel {
10     using Microsoft.Win32;
11     using System.Collections;
12     using System.ComponentModel.Design;
13     using System.Diagnostics;
14     using System.Globalization;
15     using System.Runtime.InteropServices;
16     using System.Runtime.Remoting;
17     using System.Runtime.Serialization.Formatters;
18     using System.Security.Permissions;
19
20     /// <devdoc>
21     ///    <para>Provides a type converter to convert object references to and from various
22     ///       other representations.</para>
23     /// </devdoc>
24     [HostProtection(SharedState = true)]
25     public class ReferenceConverter : TypeConverter {
26     
27         private static readonly string none = SR.GetString(SR.toStringNone);
28         private Type type;
29         
30         /// <devdoc>
31         ///    <para>
32         ///       Initializes a new instance of the <see cref='System.ComponentModel.ReferenceConverter'/> class.
33         ///    </para>
34         /// </devdoc>
35         public ReferenceConverter(Type type) {
36             this.type = type;
37         }
38
39         /// <internalonly/>
40         /// <devdoc>
41         ///    <para>Gets a value indicating whether this converter can convert an object in the
42         ///       given source type to a reference object using the specified context.</para>
43         /// </devdoc>
44         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
45             if (sourceType == typeof(string) && context != null) {
46                 return true;
47             }
48             return base.CanConvertFrom(context, sourceType);
49         }
50
51         /// <internalonly/>
52         /// <devdoc>
53         ///    <para>Converts the given object to the reference type.</para>
54         /// </devdoc>
55         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
56         
57             if (value is string) {
58                 string text = ((string)value).Trim();
59                 
60                 if (!String.Equals(text, none) && context != null) {
61                 
62                     // Try the reference service first.
63                     //
64                     IReferenceService refSvc = (IReferenceService)context.GetService(typeof(IReferenceService));
65                     if (refSvc != null) {
66                         object obj = refSvc.GetReference(text);
67                         if (obj != null) {
68                             return obj;
69                         }
70                     }
71                     
72                     // Now try IContainer
73                     //
74                     IContainer cont = context.Container;
75                     if (cont != null) {
76                         object obj = cont.Components[text];
77                         if (obj != null) {
78                             return obj;
79                         }
80                     }
81                 }
82                 return null;
83                 
84             }
85             return base.ConvertFrom(context, culture, value);
86         }
87
88         /// <internalonly/>
89         /// <devdoc>
90         ///    <para>Converts the given value object to the reference type
91         ///       using the specified context and arguments.</para>
92         /// </devdoc>
93         public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
94             if (destinationType == null) {
95                 throw new ArgumentNullException("destinationType");
96             }
97
98             if (destinationType == typeof(string)) {
99             
100                 if (value != null) {
101                     // Try the reference service first.
102                     //
103                     if (context != null) {
104                         IReferenceService refSvc = (IReferenceService)context.GetService(typeof(IReferenceService));
105                         if (refSvc != null) {
106                             string name = refSvc.GetName(value);
107                             if (name != null) {
108                                 return name;
109                             }
110                         }
111                     }
112                     
113                     // Now see if this is an IComponent.
114                     //
115                     if (!Marshal.IsComObject(value) && value is IComponent) {
116                         IComponent comp = (IComponent)value;
117                         ISite site = comp.Site;
118                         if (site != null) {
119                             string name = site.Name;
120                             if (name != null) {
121                                 return name;
122                             }
123                         }
124                     }
125
126                     // Couldn't find it.
127                     return String.Empty;
128                 }
129                 return none;
130             }
131             
132             return base.ConvertTo(context, culture, value, destinationType);
133         }
134
135         /// <internalonly/>
136         /// <devdoc>
137         ///    <para>Gets a collection of standard values for the reference data type.</para>
138         /// </devdoc>
139         public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
140         
141             object[] components = null;
142             
143             if (context != null) {
144                 ArrayList list = new ArrayList();
145                 list.Add(null);
146             
147                 // Try the reference service first.
148                 //
149                 IReferenceService refSvc = (IReferenceService)context.GetService(typeof(IReferenceService));
150                 if (refSvc != null) {
151                     object[] objs = refSvc.GetReferences(type);
152                     int count = objs.Length;
153                     
154                     for (int i = 0; i < count; i++) {
155                         if (IsValueAllowed(context, objs[i]))
156                             list.Add(objs[i]);
157                     }
158                 }
159                 else {
160                 
161                     // Now try IContainer.
162                     //
163                     IContainer cont = context.Container;
164                     if (cont != null) {
165                         ComponentCollection objs = cont.Components;
166                         
167                         foreach(IComponent obj in objs) {
168                             if (obj != null && type.IsInstanceOfType(obj) &&
169                                 IsValueAllowed(context, obj)) {
170                                 list.Add(obj);
171                             }
172                         }
173                     }
174                 }
175
176                 components = list.ToArray();
177                 Array.Sort(components, 0, components.Length, new ReferenceComparer(this));
178             }
179                 
180             return new StandardValuesCollection(components);
181         }
182     
183         /// <internalonly/>
184         /// <devdoc>
185         ///    <para>Gets a value indicating whether the list of standard values returned from
186         ///    <see cref='System.ComponentModel.ReferenceConverter.GetStandardValues'/> is an exclusive list. </para>
187         /// </devdoc>
188         public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) {
189             return true;
190         }
191         
192         /// <internalonly/>
193         /// <devdoc>
194         ///    <para>Gets a value indicating whether this object supports a standard set of values
195         ///       that can be picked from a list.</para>
196         /// </devdoc>
197         public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
198             return true;
199         }
200
201         /// <devdoc>
202         ///    <para>Gets a value indicating whether a particular value can be added to
203         ///       the standard values collection.</para>
204         /// </devdoc>
205         protected virtual bool IsValueAllowed(ITypeDescriptorContext context, object value) {
206             return true;
207         }
208         
209         /// <devdoc>
210         ///      IComparer object used for sorting references
211         /// </devdoc>
212         private class ReferenceComparer : IComparer {
213         
214             private ReferenceConverter converter;
215             
216             public ReferenceComparer(ReferenceConverter converter) {
217                 this.converter = converter;
218             }
219
220             public int Compare(object item1, object item2) {
221
222                 String itemName1 = converter.ConvertToString(item1);
223                 String itemName2 = converter.ConvertToString(item2);
224
225                 return string.Compare(itemName1, itemName2, false, CultureInfo.InvariantCulture);
226             }
227         }
228     }
229 }
230