private List<PathInfo> ParseStringPath(System.Type activityType, string path) { if (string.IsNullOrEmpty(path)) { return null; } List<PathInfo> pathInfoList = new List<PathInfo>(); PathWalker walker = new PathWalker(); PathMemberInfoEventArgs finalEventArgs = null; PathErrorInfoEventArgs errorEventArgs = null; walker.MemberFound = (EventHandler<PathMemberInfoEventArgs>) Delegate.Combine(walker.MemberFound, delegate (object sender, PathMemberInfoEventArgs eventArgs) { finalEventArgs = eventArgs; pathInfoList.Add(new PathInfo(eventArgs.Path, eventArgs.MemberInfo, BindHelpers.GetMemberType(eventArgs.MemberInfo))); }); walker.PathErrorFound = (EventHandler<PathErrorInfoEventArgs>) Delegate.Combine(walker.PathErrorFound, delegate (object sender, PathErrorInfoEventArgs eventArgs) { errorEventArgs = eventArgs; }); walker.TryWalkPropertyPath(activityType, path); return pathInfoList; }
internal static MemberInfo GetMemberInfo(Type srcType, string path) { if (srcType == null) throw new ArgumentNullException("srcType"); if (path == null) throw new ArgumentNullException("path"); if (path.Length == 0) throw new ArgumentException(SR.GetString(SR.Error_EmptyPathValue), "path"); Type propertyType = srcType; MemberInfo memberInfo = null; PathWalker pathWalker = new PathWalker(); pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { memberInfo = eventArgs.MemberInfo; if (eventArgs.MemberKind == PathMemberKind.Event) { //need to exit!!! eventArgs.Action = PathWalkAction.Stop; return; } }; if (pathWalker.TryWalkPropertyPath(propertyType, path)) return memberInfo; else return null; }
internal static object GetValue(MemberInfo memberInfo, object dataContext, string path) { if (memberInfo == null) throw new ArgumentNullException("memberInfo"); if (dataContext == null) throw new ArgumentNullException("dataContext"); if (path == null) path = string.Empty; if (string.IsNullOrEmpty(path)) return null; object targetObject = dataContext; System.Type memberType = dataContext.GetType(); PathWalker pathWalker = new PathWalker(); pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { if (targetObject == null) { eventArgs.Action = PathWalkAction.Cancel; return; } switch (eventArgs.MemberKind) { case PathMemberKind.Field: memberType = (eventArgs.MemberInfo as FieldInfo).FieldType; targetObject = (eventArgs.MemberInfo as FieldInfo).GetValue(targetObject); break; case PathMemberKind.Event: EventInfo evt = eventArgs.MemberInfo as EventInfo; memberType = evt.EventHandlerType; // GetValue() returns the actual value of the property. We need the Bind object here. // Find out if there is a matching dependency property and get the value throw the DP. DependencyObject dependencyObject = targetObject as DependencyObject; DependencyProperty dependencyProperty = DependencyProperty.FromName(evt.Name, dependencyObject.GetType()); if (dependencyProperty != null && dependencyObject != null) { if (dependencyObject.IsBindingSet(dependencyProperty)) targetObject = dependencyObject.GetBinding(dependencyProperty); else targetObject = dependencyObject.GetHandler(dependencyProperty); } else targetObject = null; // eventArgs.Action = PathWalkAction.Stop; break; case PathMemberKind.Property: memberType = (eventArgs.MemberInfo as PropertyInfo).PropertyType; if (!(eventArgs.MemberInfo as PropertyInfo).CanRead) { eventArgs.Action = PathWalkAction.Cancel; return; } targetObject = (eventArgs.MemberInfo as PropertyInfo).GetValue(targetObject, null); break; case PathMemberKind.IndexedProperty: memberType = (eventArgs.MemberInfo as PropertyInfo).PropertyType; if (!(eventArgs.MemberInfo as PropertyInfo).CanRead) { eventArgs.Action = PathWalkAction.Cancel; return; } targetObject = (eventArgs.MemberInfo as PropertyInfo).GetValue(targetObject, eventArgs.IndexParameters); break; case PathMemberKind.Index:// memberType = (eventArgs.MemberInfo as PropertyInfo).PropertyType; targetObject = (eventArgs.MemberInfo as PropertyInfo).GetValue(targetObject, BindingFlags.GetProperty, null, eventArgs.IndexParameters, CultureInfo.InvariantCulture); break; } if (targetObject == null) { if (eventArgs.LastMemberInThePath) { eventArgs.Action = PathWalkAction.Cancel; return; } else { throw new InvalidOperationException(SR.GetString(SR.Error_BindPathNullValue, eventArgs.Path)); } } }; if (pathWalker.TryWalkPropertyPath(memberType, path)) { //success return ((targetObject != dataContext) ? targetObject : null); } else { //failure return null; } }
internal static ValidationError ValidateTypesInPath(Type srcType, string path) { ValidationError error = null; if (srcType == null) throw new ArgumentNullException("srcType"); if (path == null) throw new ArgumentNullException("path"); if (path.Length == 0) throw new ArgumentException(SR.GetString(SR.Error_EmptyPathValue), "path"); Debug.Assert(WorkflowCompilationContext.Current != null, "Can't have checkTypes set to true without a context in scope"); IList<AuthorizedType> authorizedTypes = WorkflowCompilationContext.Current.GetAuthorizedTypes(); if (authorizedTypes == null) { return new ValidationError(SR.GetString(SR.Error_ConfigFileMissingOrInvalid), ErrorNumbers.Error_ConfigFileMissingOrInvalid); } Type propertyType = srcType; MemberInfo memberInfo = null; PathWalker pathWalker = new PathWalker(); pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { Type memberType = null; memberInfo = eventArgs.MemberInfo; if (memberInfo is FieldInfo) memberType = ((FieldInfo)memberInfo).FieldType; if (memberInfo is PropertyInfo) memberType = ((PropertyInfo)memberInfo).PropertyType; if (memberType != null && !SafeType(authorizedTypes, memberType)) { error = new ValidationError(SR.GetString(SR.Error_TypeNotAuthorized, memberType), ErrorNumbers.Error_TypeNotAuthorized); eventArgs.Action = PathWalkAction.Stop; return; } }; pathWalker.TryWalkPropertyPath(propertyType, path); return error; }
internal static void SetValue(object dataContext, string path, object value) { if (dataContext == null) throw new ArgumentNullException("dataContext"); if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path"); object parentObj = null; object obj = dataContext; object[] args = null; MemberInfo memberInfo = null; PathWalker pathWalker = new PathWalker(); pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { // if (obj == null) { eventArgs.Action = PathWalkAction.Cancel; return; } parentObj = obj; memberInfo = eventArgs.MemberInfo; switch (eventArgs.MemberKind) { case PathMemberKind.Field: obj = (eventArgs.MemberInfo as FieldInfo).GetValue(parentObj); args = null; break; case PathMemberKind.Event: // eventArgs.Action = PathWalkAction.Cancel; //set value is not supported on events return; case PathMemberKind.Property: obj = (eventArgs.MemberInfo as PropertyInfo).GetValue(parentObj, null); args = null; break; case PathMemberKind.IndexedProperty: case PathMemberKind.Index: obj = (eventArgs.MemberInfo as PropertyInfo).GetValue(parentObj, eventArgs.IndexParameters); args = eventArgs.IndexParameters; break; } }; if (pathWalker.TryWalkPropertyPath(dataContext.GetType(), path)) { //at this point the 'obj' holds the old value, we will be changing it to 'value' //success if (memberInfo is FieldInfo) { (memberInfo as FieldInfo).SetValue(parentObj, value); } else if (memberInfo is PropertyInfo) { if ((memberInfo as PropertyInfo).CanWrite) (memberInfo as PropertyInfo).SetValue(parentObj, value, args); else throw new InvalidOperationException(SR.GetString(SR.Error_ReadOnlyField, memberInfo.Name)); } } }
internal static object ResolveActivityPath(Activity refActivity, string path) { if (refActivity == null) throw new ArgumentNullException("refActivity"); if (path == null) throw new ArgumentNullException("path"); if (path.Length == 0) throw new ArgumentException(SR.GetString(SR.Error_EmptyPathValue), "path"); object value = refActivity; BindRecursionContext recursionContext = new BindRecursionContext(); PathWalker pathWalker = new PathWalker(); pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { // If value is null, we don't want to use GetValue on the MemberInfo if (value == null) { eventArgs.Action = PathWalkAction.Cancel; //need to cancel the walk with the failure return result return; } switch (eventArgs.MemberKind) { case PathMemberKind.Field: try { value = (eventArgs.MemberInfo as FieldInfo).GetValue(value); } catch (Exception exception) { //in some cases the value might not be there yet (e.g. validation vs. runtime) value = null; eventArgs.Action = PathWalkAction.Cancel; //we should throw only if we are at the runtime if (!refActivity.DesignMode) { TargetInvocationException targetInvocationException = exception as TargetInvocationException; throw (targetInvocationException != null) ? targetInvocationException.InnerException : exception; } } break; case PathMemberKind.Event: EventInfo evt = eventArgs.MemberInfo as EventInfo; // GetValue() returns the actual value of the property. We need the Bind object here. // Find out if there is a matching dependency property and get the value throw the DP. DependencyProperty eventDependencyProperty = DependencyProperty.FromName(evt.Name, value.GetType()); if (eventDependencyProperty != null && value is DependencyObject) { if ((value as DependencyObject).IsBindingSet(eventDependencyProperty)) value = (value as DependencyObject).GetBinding(eventDependencyProperty); else value = (value as DependencyObject).GetHandler(eventDependencyProperty); } break; case PathMemberKind.Property: if (!(eventArgs.MemberInfo as PropertyInfo).CanRead) { eventArgs.Action = PathWalkAction.Cancel; return; } // GetValue() returns the actual value of the property. We need the Bind object here. // Find out if there is a matching dependency property and get the value throw the DP. DependencyProperty dependencyProperty = DependencyProperty.FromName(eventArgs.MemberInfo.Name, value.GetType()); if (dependencyProperty != null && value is DependencyObject && (value as DependencyObject).IsBindingSet(dependencyProperty)) value = (value as DependencyObject).GetBinding(dependencyProperty); else try { value = (eventArgs.MemberInfo as PropertyInfo).GetValue(value, null); } catch (Exception exception) { //property getter function might throw at design time, validation should not fail bacause of that value = null; eventArgs.Action = PathWalkAction.Cancel; //we should throw only if we are at the runtime if (!refActivity.DesignMode) { TargetInvocationException targetInvocationException = exception as TargetInvocationException; throw (targetInvocationException != null) ? targetInvocationException.InnerException : exception; } } break; case PathMemberKind.IndexedProperty: case PathMemberKind.Index: try { value = (eventArgs.MemberInfo as PropertyInfo).GetValue(value, BindingFlags.GetProperty, null, eventArgs.IndexParameters, CultureInfo.InvariantCulture); } catch (Exception exception) { //in some cases the value might not be there yet - e.g. array or dictionary is populated at runtime only (validation vs. runtime) value = null; eventArgs.Action = PathWalkAction.Cancel; //we should throw only if we are at the runtime if (!refActivity.DesignMode) { TargetInvocationException targetInvocationException = exception as TargetInvocationException; throw (targetInvocationException != null) ? targetInvocationException.InnerException : exception; } } break; } //need to unwrap the activity bind if we get one - to proceed with the actual field/property/delegate //do not unwrap if the property/field is itself of type ActivityBind //we should not unwrap the latest ActivityBind though - only intermediate ones //avoid circular reference problems with the BindRecursionContext if (value is ActivityBind && !eventArgs.LastMemberInThePath && GetMemberType(eventArgs.MemberInfo) != typeof(ActivityBind)) { while (value is ActivityBind) { ActivityBind activityBind = value as ActivityBind; if (recursionContext.Contains(refActivity, activityBind)) throw new InvalidOperationException(SR.GetString(SR.Bind_ActivityDataSourceRecursionDetected)); recursionContext.Add(refActivity, activityBind); value = activityBind.GetRuntimeValue(refActivity); } } }; if (pathWalker.TryWalkPropertyPath(refActivity.GetType(), path)) return value; else return null; }
internal static bool CreateField(ITypeDescriptorContext context, ActivityBind activityBind, bool throwOnError) { if (!string.IsNullOrEmpty(activityBind.Path)) { Type toType = PropertyDescriptorUtils.GetBaseType(context.PropertyDescriptor, context.Instance, context); Activity component = PropertyDescriptorUtils.GetComponent(context) as Activity; if ((component != null) && (toType != null)) { component = Helpers.ParseActivityForBind(component, activityBind.Name); if (component == Helpers.GetRootActivity(component)) { bool ignoreCase = CompilerHelpers.GetSupportedLanguage(context) == SupportedLanguages.VB; Type dataSourceClass = Helpers.GetDataSourceClass(component, context); if (dataSourceClass != null) { string path = activityBind.Path; int length = path.IndexOfAny(new char[] { '.', '/', '[' }); if (length != -1) { path = path.Substring(0, length); } MemberInfo info = FindMatchingMember(path, dataSourceClass, ignoreCase); if (info != null) { Type fromType = null; bool isPrivate = false; if (info is FieldInfo) { isPrivate = ((FieldInfo) info).IsPrivate; fromType = ((FieldInfo) info).FieldType; } else if (info is PropertyInfo) { MethodInfo getMethod = ((PropertyInfo) info).GetGetMethod(); MethodInfo setMethod = ((PropertyInfo) info).GetSetMethod(); isPrivate = ((getMethod != null) && getMethod.IsPrivate) || ((setMethod != null) && setMethod.IsPrivate); } else if (info is MethodInfo) { isPrivate = ((MethodInfo) info).IsPrivate; } if (length != -1) { PathWalker walker = new PathWalker(); PathMemberInfoEventArgs finalEventArgs = null; walker.MemberFound = (EventHandler<PathMemberInfoEventArgs>) Delegate.Combine(walker.MemberFound, delegate (object sender, PathMemberInfoEventArgs eventArgs) { finalEventArgs = eventArgs; }); if (!walker.TryWalkPropertyPath(dataSourceClass, activityBind.Path)) { if (throwOnError) { throw new InvalidOperationException(SR.GetString("Error_MemberWithSameNameExists", new object[] { activityBind.Path, dataSourceClass.FullName })); } return false; } fromType = BindHelpers.GetMemberType(finalEventArgs.MemberInfo); } if (((info.DeclaringType == dataSourceClass) || !isPrivate) && ((info is FieldInfo) && TypeProvider.IsAssignable(toType, fromType))) { return true; } if (throwOnError) { throw new InvalidOperationException(SR.GetString("Error_MemberWithSameNameExists", new object[] { activityBind.Path, dataSourceClass.FullName })); } return false; } Activity activity2 = null; if (string.Compare(component.Name, path, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0) { activity2 = component; } else if ((component is CompositeActivity) && (component is CompositeActivity)) { foreach (Activity activity3 in Helpers.GetAllNestedActivities(component as CompositeActivity)) { if (string.Compare(activity3.Name, path, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0) { activity2 = activity3; } } } if (activity2 != null) { if (TypeProvider.IsAssignable(toType, activity2.GetType())) { return true; } if (throwOnError) { throw new InvalidOperationException(SR.GetString("Error_MemberWithSameNameExists", new object[] { activityBind.Path, dataSourceClass.FullName })); } return false; } IMemberCreationService service = context.GetService(typeof(IMemberCreationService)) as IMemberCreationService; if (service != null) { IDesignerHost host = context.GetService(typeof(IDesignerHost)) as IDesignerHost; if (host != null) { service.CreateField(host.RootComponentClassName, activityBind.Path, toType, null, MemberAttributes.Public, null, false); return true; } if (throwOnError) { throw new InvalidOperationException(SR.GetString("General_MissingService", new object[] { typeof(IDesignerHost).FullName })); } } else if (throwOnError) { throw new InvalidOperationException(SR.GetString("General_MissingService", new object[] { typeof(IMemberCreationService).FullName })); } } } } else { if ((component == null) && throwOnError) { throw new InvalidOperationException(SR.GetString("Error_InvalidActivityIdentifier", new object[] { activityBind.Name })); } if ((toType == null) && throwOnError) { throw new InvalidOperationException(SR.GetString("Error_PropertyTypeNotDefined", new object[] { context.PropertyDescriptor.Name, typeof(ActivityBind).Name, typeof(IDynamicPropertyTypeProvider).Name })); } } } return false; }
//given user typed path, find all properties along it and return them in the list private List<PathInfo> ParseStringPath(Type activityType, string path) { if (string.IsNullOrEmpty(path)) return null; List<PathInfo> pathInfoList = new List<PathInfo>(); PathWalker pathWalker = new PathWalker(); PathMemberInfoEventArgs finalEventArgs = null; PathErrorInfoEventArgs errorEventArgs = null; pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) { finalEventArgs = eventArgs; //store the latest args pathInfoList.Add(new PathInfo(eventArgs.Path, eventArgs.MemberInfo, BindHelpers.GetMemberType(eventArgs.MemberInfo))); }; pathWalker.PathErrorFound += delegate(object sender, PathErrorInfoEventArgs eventArgs) { errorEventArgs = eventArgs; //store the error args }; pathWalker.TryWalkPropertyPath(activityType, path); return pathInfoList; }