1 namespace System.Workflow.ComponentModel.Design
2 {
3     #region Imports
4 
5     using System;
6     using System.Drawing.Design;
7     using System.ComponentModel;
8     using System.ComponentModel.Design;
9     using System.Globalization;
10     using System.Collections;
11     using System.Collections.Generic;
12     using System.Reflection;
13     using System.CodeDom;
14     using System.Workflow.ComponentModel.Compiler;
15     using System.Collections.Specialized;
16     using System.Diagnostics;
17     using System.Text;
18 
19     #endregion
20 
21     #region Class ConditionDeclTypeConverter
22     internal sealed class ConditionTypeConverter : TypeConverter
23     {
24         internal static readonly Type RuleConditionReferenceType = null;
25         internal static readonly Type RuleDefinitionsType = null;
26         internal static readonly Type CodeConditionType = null;
27         internal static DependencyProperty DeclarativeConditionDynamicProp = null;
28         private Hashtable conditionDecls = new Hashtable();
29 
ConditionTypeConverter()30         static ConditionTypeConverter()
31         {
32             RuleConditionReferenceType = Type.GetType("System.Workflow.Activities.Rules.RuleDefinitions, " + AssemblyRef.ActivitiesAssemblyRef);
33             RuleDefinitionsType = Type.GetType("System.Workflow.Activities.Rules.RuleConditionReference, " + AssemblyRef.ActivitiesAssemblyRef);
34             CodeConditionType = Type.GetType("System.Workflow.Activities.CodeCondition, " + AssemblyRef.ActivitiesAssemblyRef);
35 
36             DeclarativeConditionDynamicProp = (DependencyProperty)RuleConditionReferenceType.GetField("RuleDefinitionsProperty").GetValue(null);
37         }
38 
ConditionTypeConverter()39         public ConditionTypeConverter()
40         {
41             string key = CodeConditionType.FullName;
42             object[] attributes = CodeConditionType.GetCustomAttributes(typeof(DisplayNameAttribute), false);
43             if (attributes != null && attributes.Length > 0 && attributes[0] is DisplayNameAttribute)
44                 key = ((DisplayNameAttribute)attributes[0]).DisplayName;
45             this.conditionDecls.Add(key, CodeConditionType);
46 
47             key = RuleDefinitionsType.FullName;
48             attributes = RuleDefinitionsType.GetCustomAttributes(typeof(DisplayNameAttribute), false);
49             if (attributes != null && attributes.Length > 0 && attributes[0] is DisplayNameAttribute)
50                 key = ((DisplayNameAttribute)attributes[0]).DisplayName;
51             this.conditionDecls.Add(key, RuleDefinitionsType);
52         }
53 
CanConvertFrom(ITypeDescriptorContext context, Type sourceType)54         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
55         {
56             if (sourceType == typeof(string))
57                 return true;
58             return base.CanConvertFrom(context, sourceType);
59         }
60 
ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)61         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
62         {
63             if (value is string)
64             {
65                 if (((string)value).Length == 0 || ((string)value) == SR.GetString(SR.NullConditionExpression))
66                     return null;
67                 else
68                     return Activator.CreateInstance(this.conditionDecls[value] as Type);
69             }
70 
71             return base.ConvertFrom(context, culture, value);
72         }
73 
CanConvertTo(ITypeDescriptorContext context, Type destinationType)74         public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
75         {
76             if (destinationType == typeof(string))
77                 return true;
78             else
79                 return base.CanConvertTo(context, destinationType);
80         }
81 
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)82         public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
83         {
84             if (value == null)
85                 return SR.GetString(SR.NullConditionExpression);
86 
87             object convertedValue = null;
88             if (destinationType == typeof(string) && value is ActivityCondition)
89             {
90                 foreach (DictionaryEntry conditionTypeEntry in this.conditionDecls)
91                 {
92                     if ((object)value.GetType() == conditionTypeEntry.Value)
93                     {
94                         convertedValue = conditionTypeEntry.Key;
95                         break;
96                     }
97                 }
98             }
99 
100             if (convertedValue == null)
101                 convertedValue = base.ConvertTo(context, culture, value, destinationType);
102 
103             return convertedValue;
104         }
GetStandardValues(ITypeDescriptorContext context)105         public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
106         {
107             ArrayList conditionDeclList = new ArrayList();
108 
109             conditionDeclList.Add(null);
110             foreach (object key in this.conditionDecls.Keys)
111             {
112                 Type declType = this.conditionDecls[key] as Type;
113                 conditionDeclList.Add(Activator.CreateInstance(declType));
114             }
115             return new StandardValuesCollection((ActivityCondition[])conditionDeclList.ToArray(typeof(ActivityCondition)));
116         }
GetStandardValuesSupported(ITypeDescriptorContext context)117         public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
118         {
119             return true;
120         }
GetStandardValuesExclusive(ITypeDescriptorContext context)121         public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
122         {
123             return true;
124         }
GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)125         public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
126         {
127             PropertyDescriptorCollection props = new PropertyDescriptorCollection(new PropertyDescriptor[] { });
128 
129             TypeConverter typeConverter = TypeDescriptor.GetConverter(value.GetType());
130             if (typeConverter != null && typeConverter.GetType() != GetType() && typeConverter.GetPropertiesSupported())
131             {
132                 return typeConverter.GetProperties(context, value, attributes);
133             }
134             else
135             {
136                 IComponent component = PropertyDescriptorUtils.GetComponent(context);
137                 if (component != null)
138                     props = PropertyDescriptorFilter.FilterProperties(component.Site, value, TypeDescriptor.GetProperties(value, new Attribute[] { BrowsableAttribute.Yes }));
139             }
140 
141             return props;
142         }
GetPropertiesSupported(ITypeDescriptorContext context)143         public override bool GetPropertiesSupported(ITypeDescriptorContext context)
144         {
145             return true;
146         }
147     }
148     #endregion
149 
150     #region ActivityBindTypeConverter
151     [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
152     public class ActivityBindTypeConverter : TypeConverter
153     {
ActivityBindTypeConverter()154         public ActivityBindTypeConverter()
155         {
156         }
157 
CanConvertFrom(ITypeDescriptorContext context, Type sourceType)158         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
159         {
160             ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
161             GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
162             if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
163                 return actualConverter.CanConvertFrom(actualContext, sourceType);
164             else if (sourceType == typeof(string))
165                 return true;
166 
167             return base.CanConvertFrom(context, sourceType);
168         }
169 
CanConvertTo(ITypeDescriptorContext context, Type destinationType)170         public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
171         {
172             if (destinationType == typeof(string) && context != null && context.PropertyDescriptor != null)
173             {
174                 ActivityBind activityBind = context.PropertyDescriptor.GetValue(context.Instance) as ActivityBind;
175                 if (activityBind != null)
176                     return true;
177             }
178 
179             ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
180             GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
181             if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
182                 return actualConverter.CanConvertTo(actualContext, destinationType);
183             else if (destinationType == typeof(string))
184                 return true;
185 
186             return base.CanConvertTo(context, destinationType);
187         }
188 
ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object valueToConvert)189         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object valueToConvert)
190         {
191             string value = valueToConvert as string;
192             if (value == null)
193                 return base.ConvertFrom(context, culture, valueToConvert);
194 
195             //Trim the value
196             value = value.Trim();
197 
198             //Check if format is "Activity=, Path="
199             string[] splitParts = Parse(value);
200             object convertedValue = (splitParts.Length == 2) ? new ActivityBind(splitParts[0], splitParts[1]) : null;
201 
202             if (convertedValue == null && (context == null || context.PropertyDescriptor == null))
203                 return base.ConvertFrom(context, culture, valueToConvert);
204 
205             //For string's only if they begin and end with " we will use the type converter
206             if (convertedValue == null)
207             {
208                 ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
209                 GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
210                 if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter) && actualConverter.CanConvertFrom(actualContext, typeof(string)))
211                     convertedValue = actualConverter.ConvertFrom(actualContext, culture, value);
212                 else
213                     convertedValue = valueToConvert;
214             }
215 
216             return convertedValue;
217         }
218 
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)219         public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
220         {
221             if (destinationType != typeof(string))
222                 return base.ConvertTo(context, culture, value, destinationType);
223 
224             string convertedValue = null;
225 
226             ActivityBind activityBind = value as ActivityBind;
227             if (activityBind != null)
228             {
229                 Activity activity = PropertyDescriptorUtils.GetComponent(context) as Activity;
230                 activity = (activity != null) ? Helpers.ParseActivityForBind(activity, activityBind.Name) : null;
231                 convertedValue = String.Format(CultureInfo.InvariantCulture, ("Activity={0}, Path={1}"), (activity != null) ? activity.QualifiedName : activityBind.Name, activityBind.Path);
232             }
233             else
234             {
235                 ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
236                 GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
237                 if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter) && actualConverter.CanConvertTo(actualContext, destinationType))
238                     convertedValue = actualConverter.ConvertTo(actualContext, culture, value, destinationType) as string;
239                 else
240                     convertedValue = base.ConvertTo(context, culture, value, destinationType) as string;
241             }
242 
243             return convertedValue;
244         }
245 
GetPropertiesSupported(ITypeDescriptorContext context)246         public override bool GetPropertiesSupported(ITypeDescriptorContext context)
247         {
248             bool propertiesSupported = false;
249             if (context != null && context.PropertyDescriptor != null)
250             {
251                 ActivityBind activityBind = context.PropertyDescriptor.GetValue(context.Instance) as ActivityBind;
252                 if (activityBind != null)
253                 {
254                     propertiesSupported = true;
255                 }
256                 else
257                 {
258                     ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
259                     GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
260                     if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
261                         propertiesSupported = actualConverter.GetPropertiesSupported(actualContext);
262                 }
263             }
264 
265             return propertiesSupported;
266         }
267 
GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)268         public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
269         {
270             ArrayList properties = new ArrayList();
271             ActivityBind activityBind = value as ActivityBind;
272             if (activityBind != null && context != null)
273             {
274                 PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value, new Attribute[] { BrowsableAttribute.Yes });
275 
276                 PropertyDescriptor activityDescriptor = props["Name"];
277                 if (activityDescriptor != null)
278                     properties.Add(new ActivityBindNamePropertyDescriptor(context, activityDescriptor));
279 
280                 PropertyDescriptor pathDescriptor = props["Path"];
281                 if (pathDescriptor != null)
282                     properties.Add(new ActivityBindPathPropertyDescriptor(context, pathDescriptor));
283             }
284             else if (context != null && context.PropertyDescriptor != null)
285             {
286                 ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
287                 GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
288                 if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
289                     properties.AddRange(actualConverter.GetProperties(actualContext, value, attributes));
290             }
291 
292             return new PropertyDescriptorCollection((PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor)));
293         }
294 
GetStandardValues(ITypeDescriptorContext context)295         public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
296         {
297             ArrayList valuesList = new ArrayList();
298             if (context == null || context.PropertyDescriptor == null)
299                 return new StandardValuesCollection(new ArrayList());
300 
301             //If the property type supports exclusive values then we need to add them to list
302             ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
303             GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
304 
305             if (actualConverter != null && actualConverter.GetStandardValuesSupported(actualContext) && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
306                 valuesList.AddRange(actualConverter.GetStandardValues(actualContext));
307 
308             return new StandardValuesCollection(valuesList.ToArray());
309         }
310 
GetStandardValuesSupported(ITypeDescriptorContext context)311         public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
312         {
313             //We do not support standard values through the
314             bool standardValuesSupported = false;
315             if (context != null && context.PropertyDescriptor != null)
316             {
317                 object existingPropertyValue = (context.Instance != null) ? context.PropertyDescriptor.GetValue(context.Instance) : null;
318                 if (!(existingPropertyValue is ActivityBind))
319                 {
320                     ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
321                     GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
322 
323                     if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
324                         standardValuesSupported = actualConverter.GetStandardValuesSupported(actualContext);
325                 }
326             }
327 
328             return standardValuesSupported;
329         }
330 
GetStandardValuesExclusive(ITypeDescriptorContext context)331         public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
332         {
333             bool exclusiveValuesSupported = false;
334             if (context != null && context.PropertyDescriptor != null)
335             {
336                 object existingPropertyValue = (context.Instance != null) ? context.PropertyDescriptor.GetValue(context.Instance) : null;
337                 if (!(existingPropertyValue is ActivityBind))
338                 {
339                     ITypeDescriptorContext actualContext = null; TypeConverter actualConverter = null;
340                     GetActualTypeConverterAndContext(context, out actualConverter, out actualContext);
341 
342                     if (actualConverter != null && actualConverter.GetType() != typeof(ActivityBindTypeConverter))
343                         exclusiveValuesSupported = actualConverter.GetStandardValuesExclusive(actualContext);
344                 }
345             }
346 
347             return exclusiveValuesSupported;
348         }
349 
350         #region Helper Methods
GetActualTypeConverterAndContext(ITypeDescriptorContext currentContext, out TypeConverter realTypeConverter, out ITypeDescriptorContext realContext)351         private void GetActualTypeConverterAndContext(ITypeDescriptorContext currentContext, out TypeConverter realTypeConverter, out ITypeDescriptorContext realContext)
352         {
353             //The following case covers the scenario where we have users writting custom property descriptors in which they have returned custom type converters
354             //In such cases we should honor the type converter returned by property descriptor only if it is not a ActivityBindTypeConverter
355             //If it is ActivityBindTypeConveter then we should lookup the converter based on Property type
356             //Please be care ful when you change this code as it will break ParameterInfoBasedPropertyDescriptor
357             realContext = currentContext;
358             realTypeConverter = null;
359 
360             if (currentContext != null && currentContext.PropertyDescriptor != null)
361             {
362                 realTypeConverter = TypeDescriptor.GetConverter(currentContext.PropertyDescriptor.PropertyType);
363 
364                 ActivityBindPropertyDescriptor activityBindPropertyDescriptor = currentContext.PropertyDescriptor as ActivityBindPropertyDescriptor;
365                 if (activityBindPropertyDescriptor != null &&
366                     activityBindPropertyDescriptor.RealPropertyDescriptor != null &&
367                     activityBindPropertyDescriptor.RealPropertyDescriptor.Converter != null &&
368                     activityBindPropertyDescriptor.RealPropertyDescriptor.Converter.GetType() != typeof(ActivityBindTypeConverter))
369                 {
370                     realTypeConverter = activityBindPropertyDescriptor.RealPropertyDescriptor.Converter;
371                     realContext = new TypeDescriptorContext(currentContext, activityBindPropertyDescriptor.RealPropertyDescriptor, currentContext.Instance);
372                 }
373             }
374         }
375 
Parse(string value)376         private string[] Parse(string value)
377         {
378             string[] splitValues = value.Split(new char[] { ',' }, 2); //array could be multi-dimentional
379             if (splitValues.Length == 2)
380             {
381                 string activityIDMatch = "Activity=";
382                 string pathMatch = "Path=";
383 
384                 string activityID = splitValues[0].Trim();
385                 string path = splitValues[1].Trim();
386                 if (activityID.StartsWith(activityIDMatch, StringComparison.OrdinalIgnoreCase) &&
387                     path.StartsWith(pathMatch, StringComparison.OrdinalIgnoreCase))
388                 {
389                     activityID = activityID.Substring(activityIDMatch.Length);
390                     path = path.Substring(pathMatch.Length);
391                     return new String[] { activityID, path };
392                 }
393             }
394 
395             return new string[] { };
396         }
397         #endregion
398     }
399     #endregion
400 
401     #region ActivityBindPathTypeConverter
402     internal sealed class ActivityBindPathTypeConverter : PropertyValueProviderTypeConverter
403     {
CanConvertFrom(ITypeDescriptorContext context, Type sourceType)404         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
405         {
406             return new StringConverter().CanConvertFrom(context, sourceType);
407         }
408 
CanConvertTo(ITypeDescriptorContext context, Type destinationType)409         public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
410         {
411             return new StringConverter().CanConvertTo(context, destinationType);
412         }
413 
ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)414         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
415         {
416             return new StringConverter().ConvertFrom(context, culture, value);
417         }
418 
ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)419         public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
420         {
421             return new StringConverter().ConvertTo(context, culture, value, destinationType);
422         }
423     }
424     #endregion
425 }
426