1 // Copyright (c) 1999-2002 Microsoft Corporation. All rights reserved.
3 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
4 // WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
5 // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
6 // THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE
7 // AND INFORMATION REMAINS WITH THE USER.
10 using System.ComponentModel;
11 using System.ComponentModel.Design;
12 using System.Collections;
13 using System.Collections.Generic;
14 using System.Resources;
15 using System.Reflection;
16 using System.Globalization;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Workflow.ComponentModel;
20 using System.Workflow.ComponentModel.Compiler;
21 using System.Workflow.ComponentModel.Design;
23 /*********************************************************************
24 * NOTE: A copy of this file exists at: WF\Common\Shared
25 * The two files must be kept in sync. Any change made here must also
26 * be made to WF\Common\Shared\BasePropertyDescriptor.cs
27 *********************************************************************/
29 namespace System.Workflow.Activities.Common
31 #region Class PropertyDescriptorUtils
32 internal static class PropertyDescriptorUtils
34 internal static ISite GetSite(IServiceProvider serviceProvider, object component)
38 if (component != null)
40 if ((component is IComponent) && ((IComponent)component).Site != null)
41 site = ((IComponent)component).Site;
43 if (site == null && component.GetType().IsArray && (component as object[]).Length > 0 && (component as object[])[0] is IComponent)
44 site = ((IComponent)(component as object[])[0]).Site;
46 if (site == null && serviceProvider != null)
48 IReferenceService referenceService = serviceProvider.GetService(typeof(IReferenceService)) as IReferenceService;
49 if (referenceService != null)
51 IComponent baseComponent = referenceService.GetComponent(component);
52 if (baseComponent != null)
53 site = baseComponent.Site;
59 site = serviceProvider as ISite;
64 internal static IComponent GetComponent(ITypeDescriptorContext context)
66 ISite site = (context != null) ? GetSite(context, context.Instance) : null;
67 return (site != null) ? site.Component : null;
70 internal static Type GetBaseType(PropertyDescriptor property, object owner, IServiceProvider serviceProvider)
74 Type ownerType = owner.GetType();
77 IDynamicPropertyTypeProvider basetypeProvider = owner as IDynamicPropertyTypeProvider;
78 if (basetypeProvider != null)
79 baseType = basetypeProvider.GetPropertyType(serviceProvider, property.Name);
83 baseType = property.PropertyType;
88 internal static void SetPropertyValue(IServiceProvider serviceProvider, PropertyDescriptor propertyDescriptor, object component, object value)
90 ComponentChangeDispatcher componentChange = new ComponentChangeDispatcher(serviceProvider, component, propertyDescriptor);
93 propertyDescriptor.SetValue(component, value);
97 // If there was a problem setting the controls property then we get:
98 // ArgumentException (from properties set method)
99 // ==> Becomes inner exception of TargetInvocationException
101 // Propagate the original exception up
102 if (t is TargetInvocationException && t.InnerException != null)
103 throw t.InnerException;
109 componentChange.Dispose();
115 #region Class ComponentChangeDispatcher
116 internal sealed class ComponentChangeDispatcher : IDisposable
118 private IServiceProvider serviceProvider;
119 private object component;
120 private PropertyDescriptor property;
121 private object oldValue;
122 private object newValue;
124 public ComponentChangeDispatcher(IServiceProvider serviceProvider, object component, PropertyDescriptor propertyDescriptor)
126 this.serviceProvider = serviceProvider;
127 this.component = component;
128 this.property = propertyDescriptor;
130 IComponentChangeService changeService = serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
131 if (changeService != null)
135 newValue = oldValue = propertyDescriptor.GetValue(component);
136 propertyDescriptor.AddValueChanged(component, new EventHandler(OnValueChanged));
137 changeService.OnComponentChanging(component, propertyDescriptor);
139 catch (CheckoutException coEx)
141 if (coEx == CheckoutException.Canceled)
148 public void Dispose()
150 IComponentChangeService changeService = this.serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
151 if (changeService != null)
152 changeService.OnComponentChanged(this.component, this.property, this.oldValue, this.newValue);
155 private void OnValueChanged(object sender, EventArgs e)
157 this.newValue = this.property.GetValue(this.component);
158 this.property.RemoveValueChanged(this.component, new EventHandler(OnValueChanged));
163 #region Class DynamicPropertyDescriptor
164 internal class DynamicPropertyDescriptor : PropertyDescriptor
166 private IServiceProvider serviceProvider;
167 private PropertyDescriptor realPropertyDescriptor;
169 public DynamicPropertyDescriptor(IServiceProvider serviceProvider, PropertyDescriptor descriptor)
170 : base(descriptor, null)
172 this.serviceProvider = serviceProvider;
173 this.realPropertyDescriptor = descriptor;
176 public IServiceProvider ServiceProvider
180 return this.serviceProvider;
184 public PropertyDescriptor RealPropertyDescriptor
188 return this.realPropertyDescriptor;
192 public override string Category
196 return this.realPropertyDescriptor.Category;
200 public override AttributeCollection Attributes
204 ArrayList attributes = new ArrayList();
205 attributes.AddRange(this.realPropertyDescriptor.Attributes);
206 attributes.Add(new MergablePropertyAttribute(false));
207 return new AttributeCollection((Attribute[])attributes.ToArray(typeof(Attribute)));
211 public override TypeConverter Converter
215 return this.realPropertyDescriptor.Converter;
219 public override string Description
223 return this.realPropertyDescriptor.Description;
227 public override string DisplayName
231 return this.realPropertyDescriptor.DisplayName;
235 public override Type ComponentType
239 return this.realPropertyDescriptor.ComponentType;
243 public override Type PropertyType
247 return this.realPropertyDescriptor.PropertyType;
251 public override bool IsReadOnly
255 return this.realPropertyDescriptor.IsReadOnly;
259 public override void ResetValue(object component)
261 this.realPropertyDescriptor.ResetValue(component);
264 public override bool CanResetValue(object component)
266 return this.realPropertyDescriptor.CanResetValue(component);
269 public override bool ShouldSerializeValue(object component)
271 // work around: The real property descriptor is returning false for all the
272 // SequentialWorkflow class's properties because they all get replaced with
273 // InheritedPropertyDescriptors on Initialization (in the ComponentDesigner
274 // base class), which is causing problems in the code-only serialization.
275 if (string.Equals(this.realPropertyDescriptor.GetType().FullName, "System.ComponentModel.Design.InheritedPropertyDescriptor", StringComparison.Ordinal))
278 return this.realPropertyDescriptor.ShouldSerializeValue(component);
281 public override object GetValue(object component)
283 // When a child property is of type event, component could be null.
284 if (component == null)
287 return this.realPropertyDescriptor.GetValue(component);
290 public override void SetValue(object component, object value)
292 if (component is IComponent)
293 this.realPropertyDescriptor.SetValue(component, value);
295 PropertyDescriptorUtils.SetPropertyValue(ServiceProvider, this.realPropertyDescriptor, component, value);
300 #region Class ParameterInfoBasedPropertyDescriptor
302 internal class ParameterInfoBasedPropertyDescriptor : PropertyDescriptor
304 private Type componentType;
305 private string desc = string.Empty;
306 private bool avoidDuplication = false;
307 private object parameter = null; // Could be either ParameterInfo or PropertyInfo
308 private Type parameterType = null;
309 private const string parameterPrefix = "(Parameter) ";
311 internal ParameterInfoBasedPropertyDescriptor(Type componentType, ParameterInfo paramInfo, bool avoidDuplication, params Attribute[] attributes)
312 : base((paramInfo.Position == -1) ? "(ReturnValue)" : paramInfo.Name, attributes)
314 if (componentType == null)
315 throw new ArgumentNullException("componentType");
317 if (paramInfo == null)
318 throw new ArgumentNullException("paramInfo");
320 if (paramInfo.ParameterType == null)
321 throw new InvalidOperationException(SR.GetString(SR.Error_ParameterTypeResolution, paramInfo.Name));
323 this.componentType = componentType;
324 this.parameter = paramInfo;
325 this.avoidDuplication = avoidDuplication;
326 this.parameterType = paramInfo.ParameterType;
328 //Build and cache description
329 string qualifier = String.Empty;
330 if ((paramInfo.ParameterType != null) && (paramInfo.ParameterType.IsByRef || (paramInfo.IsIn && paramInfo.IsOut)))
331 qualifier = SR.GetString(SR.Ref);
332 else if (paramInfo.IsOut || paramInfo.Name == null)
333 qualifier = SR.GetString(SR.Out);
335 qualifier = SR.GetString(SR.In);
336 this.desc = SR.GetString(SR.ParameterDescription, paramInfo.ParameterType.FullName);
340 internal ParameterInfoBasedPropertyDescriptor(Type componentType, string propertyName, Type propertyType, bool avoidDuplication, params Attribute[] attributes)
341 : base(propertyName, attributes)
343 if (componentType == null)
344 throw new ArgumentNullException("componentType");
346 if (propertyType == null)
347 throw new InvalidOperationException(SR.GetString(SR.Error_ParameterTypeResolution, propertyName));
349 this.componentType = componentType;
350 this.parameterType = propertyType;
351 this.avoidDuplication = avoidDuplication;
352 this.desc = SR.GetString(SR.InvokeParameterDescription, propertyType.FullName.ToString());
355 internal Type ParameterType
359 Type type = this.parameterType;
361 type = type.GetElementType();
366 public override string Description
374 public override string Category
378 return SR.GetString(SR.Parameters);
382 public override object GetEditor(Type editorBaseType)
384 return TypeDescriptor.GetEditor(PropertyType, editorBaseType);
387 public override string DisplayName
395 public override bool IsReadOnly
403 public override Type ComponentType
407 return this.componentType;
411 public override string Name
415 if (this.avoidDuplication)
417 // WinOE Bug 10442: should only prefix with "(Parameter)" if there is and existing
418 // member of the same name.
419 return GetParameterPropertyName(this.componentType, base.Name);
426 internal static MemberInfo FindMatchingMember(string name, Type ownerType, bool ignoreCase)
428 MemberInfo matchingMember = null;
429 foreach (MemberInfo memberInfo in ownerType.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
431 if (memberInfo.Name.Equals(name, ((ignoreCase) ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture)))
433 matchingMember = memberInfo;
437 return matchingMember;
440 public override Type PropertyType
444 Type propertyType = ParameterType;
445 if (propertyType == null)
446 propertyType = typeof(ActivityBind);
451 public override TypeConverter Converter
455 //We return this to make sure that we can bind parameters through UI
456 return new ActivityBindTypeConverter();
460 public override AttributeCollection Attributes
464 ArrayList attributes = new ArrayList();
465 attributes.AddRange(base.Attributes);
466 attributes.AddRange(TypeDescriptor.GetAttributes(PropertyType));
467 return new AttributeCollection((Attribute[])attributes.ToArray(typeof(Attribute)));
471 public override void ResetValue(object component)
473 if (PropertyType != null && !PropertyType.IsValueType)
474 SetValue(component, null);
477 public override bool CanResetValue(object component)
482 public override bool ShouldSerializeValue(object component)
487 public override void SetValue(object component, object value)
489 // the logic for notifications is borrowed from ReflectPropertyDescritpor
490 if (component == null)
493 IServiceProvider serviceProvider = GetSite(component);
494 ComponentChangeDispatcher componentChange = (serviceProvider != null) ? new ComponentChangeDispatcher(serviceProvider, component, this) : null;
498 WorkflowParameterBindingCollection parameters = GetParameterBindings(component);
499 if (parameters != null)
501 string propertyName = String.Empty;
502 if (this.Name.StartsWith(parameterPrefix, StringComparison.Ordinal))
503 propertyName = this.Name.Substring(parameterPrefix.Length);
505 propertyName = this.Name;
507 WorkflowParameterBinding binding = null;
508 if (parameters.Contains(propertyName))
509 binding = parameters[propertyName];
512 binding = new WorkflowParameterBinding(propertyName);
513 parameters.Add(binding);
516 if (value is ActivityBind)
517 binding.SetBinding(WorkflowParameterBinding.ValueProperty, value as ActivityBind);
519 binding.SetValue(WorkflowParameterBinding.ValueProperty, value);
521 OnValueChanged(component, EventArgs.Empty);
526 // If there was a problem setting the controls property then we get:
527 // ArgumentException (from properties set method)
528 // ==> Becomes inner exception of TargetInvocationException
530 // Propagate the original exception up
531 if (t is TargetInvocationException && t.InnerException != null)
532 throw t.InnerException;
538 // Now notify the change service that the change was successful.
539 if (componentChange != null)
540 componentChange.Dispose();
544 public override object GetValue(object component)
546 WorkflowParameterBindingCollection parameters = GetParameterBindings(component);
547 string displayName = this.Name;
548 string propertyName = (displayName.StartsWith(parameterPrefix, StringComparison.Ordinal)) ? displayName.Substring(parameterPrefix.Length) : displayName;
549 if (parameters != null && parameters.Contains(propertyName))
551 if (parameters[propertyName].IsBindingSet(WorkflowParameterBinding.ValueProperty))
552 return parameters[propertyName].GetBinding(WorkflowParameterBinding.ValueProperty);
554 return parameters[propertyName].GetValue(WorkflowParameterBinding.ValueProperty);
560 private WorkflowParameterBindingCollection GetParameterBindings(object component)
562 WorkflowParameterBindingCollection retVal = null;
563 MemberInfo memberInfo = component.GetType().GetProperty("ParameterBindings", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.ExactBinding, null, typeof(WorkflowParameterBindingCollection), new Type[] { }, new ParameterModifier[] { });
564 if (memberInfo != null)
565 retVal = component.GetType().InvokeMember("ParameterBindings", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.ExactBinding, null, component, new object[] { }, CultureInfo.InvariantCulture) as WorkflowParameterBindingCollection;
569 public static string GetParameterPropertyName(Type componentType, string paramName)
571 string paramPropertyName = paramName;
572 if (FindMatchingMember(paramName, componentType, false) != null)
573 paramPropertyName = parameterPrefix + paramName;
575 return paramPropertyName;
580 #region IPropertyValueProvider Interface
581 internal interface IPropertyValueProvider
583 ICollection GetPropertyValues(ITypeDescriptorContext typeDescriptorContext);
587 #region Class PropertyValueProviderTypeConverter
588 internal class PropertyValueProviderTypeConverter : TypeConverter
590 public PropertyValueProviderTypeConverter()
594 public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
596 // grab all property values
597 IPropertyValueProvider valuesProvider = null;
598 object[] instances = context.Instance as object[];
599 if (instances != null && instances.Length > 0)
600 valuesProvider = instances[0] as IPropertyValueProvider;
602 valuesProvider = context.Instance as IPropertyValueProvider;
604 ICollection values = new object[] { };
605 if (valuesProvider != null)
606 values = valuesProvider.GetPropertyValues(context);
608 return new StandardValuesCollection(values);
611 public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
616 public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
623 #region Class TypePropertyDescriptor
624 internal class TypePropertyDescriptor : DynamicPropertyDescriptor
626 public TypePropertyDescriptor(IServiceProvider serviceProvider, PropertyDescriptor actualPropDesc)
627 : base(serviceProvider, actualPropDesc)
631 public override TypeConverter Converter
635 // work around: a direct type comparison would not work because the types in this file are compiled
636 // into the component model and the activities dll separately. The assembly name differs thus
637 // the comparison fails. Work around by getting the type from the same assembly before doing
639 TypeConverter baseTypeConverter = base.Converter;
640 string baseConverterTypeName = baseTypeConverter.GetType().FullName;
641 Type baseConverterType = Assembly.GetExecutingAssembly().GetType(baseConverterTypeName);
642 if (baseConverterType != null && typeof(TypePropertyTypeConverter).IsAssignableFrom(baseConverterType))
643 return baseTypeConverter;
645 return new TypePropertyTypeConverter();
649 public override object GetValue(object component)
651 if (component == null)
652 throw new ArgumentNullException("component");
654 object value = base.GetValue(component);
658 // See if there is a value in the user data DesignTimeTypeNames hashtable.
659 // If yes, it's probably a wrong type name. Show the name anyway.
660 DependencyObject dependencyObject = component as DependencyObject;
661 if (dependencyObject != null)
663 object key = DependencyProperty.FromName(this.RealPropertyDescriptor.Name, this.RealPropertyDescriptor.ComponentType);
664 value = Helpers.GetDesignTimeTypeName(dependencyObject, key);
665 if (string.IsNullOrEmpty(value as string))
667 key = this.RealPropertyDescriptor.ComponentType.FullName + "." + this.RealPropertyDescriptor.Name;
668 value = Helpers.GetDesignTimeTypeName(dependencyObject, key);
676 public override void SetValue(object component, object value)
678 if (component == null)
679 throw new ArgumentNullException("component");
683 Type type = value as Type;
684 ITypeFilterProvider filterProvider = PropertyDescriptorUtils.GetComponent(new TypeDescriptorContext(ServiceProvider, RealPropertyDescriptor, component)) as ITypeFilterProvider;
685 if (filterProvider != null)
686 filterProvider.CanFilterType(type, true); //this will throw an exception if the type is not correctly filterable
689 base.SetValue(component, value);
694 #region Class TypePropertyValueProviderTypeConverter
695 internal class TypePropertyValueProviderTypeConverter : TypePropertyTypeConverter
697 // NOTE: Copied from PropertyValueProviderTypeConverter.
698 // The purpose of this type converter is so that we can both provide standard values and
699 // convert System.Type to string.
700 public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
702 // grab all property values
703 IPropertyValueProvider valuesProvider = null;
704 object[] instances = context.Instance as object[];
705 if (instances != null && instances.Length > 0)
706 valuesProvider = instances[0] as IPropertyValueProvider;
708 valuesProvider = context.Instance as IPropertyValueProvider;
710 ICollection values = new object[] { };
711 if (valuesProvider != null && context != null)
712 values = valuesProvider.GetPropertyValues(context);
714 return new StandardValuesCollection(values);
716 public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
720 public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
727 #region Class TypePropertyTypeConverter
728 internal class TypePropertyTypeConverter : TypeConverter
730 public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
732 if (sourceType == null)
733 throw new ArgumentNullException("sourceType");
735 if (TypeDescriptor.Equals(sourceType, typeof(string)))
738 return base.CanConvertFrom(context, sourceType);
742 public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
744 if (destinationType == null)
745 throw new ArgumentNullException("destinationType");
747 if (TypeDescriptor.Equals(destinationType, typeof(Type)))
750 return base.CanConvertTo(context, destinationType);
753 public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object valueToConvert)
755 string typeName = valueToConvert as string;
756 if (String.IsNullOrEmpty(typeName))
761 ITypeProvider typeProvider = context.GetService(typeof(ITypeProvider)) as ITypeProvider;
762 if (typeProvider != null)
763 return typeProvider.GetType(typeName, true);
766 return base.ConvertFrom(context, culture, valueToConvert);
769 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
771 if (value is Type && TypeDescriptor.Equals(destinationType, typeof(string)))
772 return ((Type)value).FullName;
774 return base.ConvertTo(context, culture, value, destinationType);