// Copyright (c) Microsoft Corporation. All rights reserved. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, // WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. // THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE // AND INFORMATION REMAINS WITH THE USER. /********************************************************************* * NOTE: A copy of this file exists at: WF\Activities\Common * The two files must be kept in sync. Any change made here must also * be made to WF\Activities\Common\CompModHelpers.cs *********************************************************************/ namespace System.Workflow.ComponentModel.Design { using System; using System.CodeDom; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Workflow.ComponentModel.Serialization; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; using System.Drawing; using System.Drawing.Design; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Compiler; using System.Text; using System.Reflection; using System.Xml; using System.Globalization; using Microsoft.Win32; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; #region Class Helpers internal static class Helpers { private static readonly string VSExtensionProductRegistrySubKey = "Visual Studio Ext for Windows Workflow"; // internal static readonly string ProductRootRegKey = @"SOFTWARE\Microsoft\Net Framework Setup\NDP\v4.0\Setup\Windows Workflow Foundation"; internal static readonly string ProductInstallDirectory = GetInstallDirectory(false); internal static readonly string ProductSDKInstallDirectory = GetInstallDirectory(true); internal static readonly string TypeProviderAssemblyRegValueName = "References"; private static readonly string ProductRootRegKey30 = @"SOFTWARE\Microsoft\Net Framework Setup\NDP\v3.0\Setup\Windows Workflow Foundation"; internal static readonly string ProductInstallDirectory30 = GetInstallDirectory30(); private const string ProductCode = "{B644FB52-BB3D-4C43-80EC-57644210536A}"; private const string ProductSDKCode = "{C8A7718A-FF6D-4DDC-AE36-BBF968D6799B}"; private const string INSTALLPROPERTY_INSTALLLOCATION = "InstallLocation"; internal const int FILENAME_MAX = 260; //"stdio.h" [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "LastIndexOf(\"\\\") not a security issue.")] [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string PerUserRegistryKey { get { string keyPath = String.Empty; using (RegistryKey userRegistryKey = Application.UserAppDataRegistry) { keyPath = userRegistryKey.ToString().Substring(Registry.CurrentUser.ToString().Length + 1); keyPath = keyPath.Substring(0, keyPath.LastIndexOf("\\")); keyPath += "\\" + VSExtensionProductRegistrySubKey; } return keyPath; } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private static string TypeProviderRegistryKeyPath { get { return PerUserRegistryKey + "\\TypeProvider"; } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool IsFileNameValid(string fileName) { int length = Path.GetInvalidPathChars().GetLength(0) + 5; char[] invalidChars = new char[length]; Path.GetInvalidPathChars().CopyTo(invalidChars, 0); invalidChars[length - 5] = ':'; invalidChars[length - 4] = '?'; invalidChars[length - 3] = '*'; invalidChars[length - 2] = '/'; invalidChars[length - 1] = '\\'; return (fileName != null && fileName.Length != 0 && fileName.Length <= FILENAME_MAX && fileName.IndexOfAny(invalidChars) == -1); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool AreAllActivities(ICollection c) { if (c == null) throw new ArgumentNullException("c"); foreach (object obj in c) { if (!(obj is Activity)) return false; } return true; } // this will return IDictionary, whose keys are parent and value is arraylist of child activities [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static IDictionary PairUpCommonParentActivities(ICollection activities) { if (activities == null) throw new ArgumentNullException("activities"); Hashtable commonParentActivities = new Hashtable(); foreach (Activity activity in activities) { if (activity.Parent != null) { ArrayList childActivities = (ArrayList)commonParentActivities[activity.Parent]; if (childActivities == null) { childActivities = new ArrayList(); commonParentActivities.Add(activity.Parent, childActivities); } childActivities.Add(activity); } } return commonParentActivities; } // this will remove any activity from the collection whose parent is already there in the collection [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity[] GetTopLevelActivities(ICollection activities) { if (activities == null) throw new ArgumentNullException("activities"); List filteredActivities = new List(); foreach (object obj in activities) { Activity activity = obj as Activity; if (activity != null) { bool foundParent = false; Activity parentActivity = activity.Parent; while (parentActivity != null && !foundParent) { foreach (object obj2 in activities) { if (obj2 == parentActivity) { foundParent = true; break; } } parentActivity = parentActivity.Parent; } if (!foundParent) filteredActivities.Add(activity); } } return filteredActivities.ToArray(); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity[] GetNestedActivities(CompositeActivity compositeActivity) { if (compositeActivity == null) throw new ArgumentNullException("compositeActivity"); IList childActivities = null; ArrayList nestedActivities = new ArrayList(); Queue compositeActivities = new Queue(); compositeActivities.Enqueue(compositeActivity); while (compositeActivities.Count > 0) { CompositeActivity compositeActivity2 = (CompositeActivity)compositeActivities.Dequeue(); childActivities = compositeActivity2.Activities; foreach (Activity activity in childActivities) { nestedActivities.Add(activity); if (activity is CompositeActivity) compositeActivities.Enqueue(activity); } } return (Activity[])nestedActivities.ToArray(typeof(Activity)); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static IList GetIdentifiersInCompositeActivity(CompositeActivity compositeActivity) { ArrayList identifiers = new ArrayList(); if (compositeActivity != null) { identifiers.Add(compositeActivity.Name); IList allChildren = GetAllNestedActivities(compositeActivity); foreach (Activity activity in allChildren) identifiers.Add(activity.Name); } return ArrayList.ReadOnly(identifiers); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity[] GetAllNestedActivities(CompositeActivity compositeActivity) { if (compositeActivity == null) throw new ArgumentNullException("compositeActivity"); ArrayList nestedActivities = new ArrayList(); // Note: GetAllNestedActivities will not check for black box activities. // This is to allow it to be invoked from within the activity's // constructor. //if(Helpers.IsCustomActivity(compositeActivity)) //return (Activity[])nestedActivities.ToArray(typeof(Activity)); Queue compositeActivities = new Queue(); compositeActivities.Enqueue(compositeActivity); while (compositeActivities.Count > 0) { CompositeActivity compositeActivity2 = (CompositeActivity)compositeActivities.Dequeue(); if (compositeActivity2 == compositeActivity || !Helpers.IsCustomActivity(compositeActivity2)) { foreach (Activity activity in compositeActivity2.Activities) { nestedActivities.Add(activity); if (activity is CompositeActivity) compositeActivities.Enqueue(activity); } foreach (Activity activity in compositeActivity2.EnabledActivities) { if (!nestedActivities.Contains(activity)) { nestedActivities.Add(activity); if (activity is CompositeActivity) compositeActivities.Enqueue(activity); } } } } return (Activity[])nestedActivities.ToArray(typeof(Activity)); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string MergeNamespaces(string primaryNs, string secondaryNs) { string newNs = primaryNs; if (secondaryNs != null && secondaryNs.Length > 0) { if (newNs != null && newNs.Length > 0) newNs += ("." + secondaryNs); else newNs = secondaryNs; } if (newNs == null) newNs = string.Empty; return newNs; } internal static Activity GetRootActivity(Activity activity) { if (activity == null) throw new ArgumentNullException("activity"); while (activity.Parent != null) activity = activity.Parent; return activity; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Stream SerializeDesignersToStream(ICollection activities) { Stream stateStream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stateStream); Queue serializedComponents = new Queue(); foreach (IComponent activity in activities) serializedComponents.Enqueue(activity); while (serializedComponents.Count > 0) { IComponent component = serializedComponents.Dequeue(); if (component != null && component.Site != null) { IDesignerHost designerHost = component.Site.GetService(typeof(IDesignerHost)) as IDesignerHost; if (designerHost == null) throw new InvalidOperationException( SR.GetString(SR.General_MissingService, typeof(IDesignerHost).Name)); ActivityDesigner activityDesigner = designerHost.GetDesigner(component) as ActivityDesigner; if (activityDesigner != null) { try { ((IPersistUIState)activityDesigner).SaveViewState(writer); CompositeActivity compositeActivity = component as CompositeActivity; if (compositeActivity != null) { foreach (IComponent childActivity in compositeActivity.Activities) { serializedComponents.Enqueue(childActivity); } } } catch { } } } } return stateStream; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void DeserializeDesignersFromStream(ICollection activities, Stream stateStream) { if (stateStream.Length == 0) return; BinaryReader reader = new BinaryReader(stateStream); stateStream.Seek(0, SeekOrigin.Begin); Queue serializedComponents = new Queue(); foreach (IComponent component in activities) serializedComponents.Enqueue(component); while (serializedComponents.Count > 0) { IComponent component = serializedComponents.Dequeue(); if (component != null && component.Site != null) { IDesignerHost designerHost = component.Site.GetService(typeof(IDesignerHost)) as IDesignerHost; if (designerHost == null) throw new InvalidOperationException( SR.GetString(SR.General_MissingService, typeof(IDesignerHost).Name)); ActivityDesigner activityDesigner = designerHost.GetDesigner(component) as ActivityDesigner; if (activityDesigner != null) { try { ((IPersistUIState)activityDesigner).LoadViewState(reader); CompositeActivity compositeActivity = component as CompositeActivity; if (compositeActivity != null) { foreach (IComponent childActivity in compositeActivity.Activities) { serializedComponents.Enqueue(childActivity); } } } catch { } } } } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string GetBaseIdentifier(Activity activity) { string baseIdentifier = activity.GetType().Name; StringBuilder b = new StringBuilder(baseIdentifier.Length); for (int i = 0; i < baseIdentifier.Length; i++) { if (Char.IsUpper(baseIdentifier[i]) && (i == 0 || i == baseIdentifier.Length - 1 || Char.IsUpper(baseIdentifier[i + 1]))) { b.Append(Char.ToLowerInvariant(baseIdentifier[i])); } else { b.Append(baseIdentifier.Substring(i)); break; } } return b.ToString(); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string GetRootNamespace(IServiceProvider serviceProvider) { if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); string rootNs = string.Empty; IWorkflowCompilerOptionsService compilerOptionsService = (IWorkflowCompilerOptionsService)serviceProvider.GetService(typeof(IWorkflowCompilerOptionsService)); if (compilerOptionsService != null && compilerOptionsService.RootNamespace != null) rootNs = compilerOptionsService.RootNamespace; //e.g. WorkflowApp1 return rootNs; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Type GetDataSourceClass(Activity activity, IServiceProvider serviceProvider) { if (activity == null) throw new ArgumentNullException("activity"); if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); Type activityType = null; string className = null; if (activity == GetRootActivity(activity)) className = activity.GetValue(WorkflowMarkupSerializer.XClassProperty) as String; if (!String.IsNullOrEmpty(className)) { ITypeProvider typeProvider = (ITypeProvider)serviceProvider.GetService(typeof(ITypeProvider)); if (typeProvider == null) throw new InvalidOperationException( SR.GetString(SR.General_MissingService, typeof(ITypeProvider).Name)); activityType = typeProvider.GetType(className); } else { return activity.GetType(); } return activityType; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity GetDataSourceActivity(Activity activity, string inputName, out string name) { if (activity == null) throw new ArgumentNullException("activity"); if (string.IsNullOrEmpty(inputName)) throw new ArgumentException("inputName"); name = inputName; if (inputName.IndexOf('.') == -1) return activity; int indexOfDot = inputName.LastIndexOf('.'); string scopeID = inputName.Substring(0, indexOfDot); name = inputName.Substring(indexOfDot + 1); Activity contextActivity = Helpers.ParseActivityForBind(activity, scopeID); if (contextActivity == null) contextActivity = Helpers.ParseActivity(Helpers.GetRootActivity(activity), scopeID); // activity can be either the qualified id of the scope activity or the qualified id of the custom activity. return contextActivity; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void GetNamespaceAndClassName(string fullQualifiedName, out string namespaceName, out string className) { namespaceName = String.Empty; className = String.Empty; if (fullQualifiedName == null) return; int indexOfDot = fullQualifiedName.LastIndexOf('.'); if (indexOfDot != -1) { namespaceName = fullQualifiedName.Substring(0, indexOfDot); className = fullQualifiedName.Substring(indexOfDot + 1); } else { className = fullQualifiedName; } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static CodeTypeDeclaration GetCodeNamespaceAndClass(CodeNamespaceCollection namespaces, string namespaceName, string className, out CodeNamespace codeNamespace) { codeNamespace = null; foreach (CodeNamespace ns in namespaces) { if (ns.Name == namespaceName) { codeNamespace = ns; break; } } CodeTypeDeclaration codeTypeDeclaration = null; if (codeNamespace != null) { foreach (CodeTypeDeclaration typeDecl in codeNamespace.Types) { if (typeDecl.Name == className) { codeTypeDeclaration = typeDecl; break; } } } return codeTypeDeclaration; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string GetClassName(string fullQualifiedName) { if (fullQualifiedName == null) return null; string className = fullQualifiedName; int indexOfDot = fullQualifiedName.LastIndexOf('.'); if (indexOfDot != -1) className = fullQualifiedName.Substring(indexOfDot + 1); return className; } [DllImport("msi.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] private static extern int MsiGetProductInfoW(string szProduct, string szProperty, StringBuilder lpValueBuf, ref int pcchValueBuf); private static string GetInstallDirectory(bool getSDKDir) { string path = string.Empty; try { //ERROR_UNKNOWN_PROPERTY 1608L //ERROR_INVALID_PARAMETER 87L int length = FILENAME_MAX + 1; StringBuilder location = new StringBuilder(length); int hr = MsiGetProductInfoW(getSDKDir ? ProductSDKCode : ProductCode, INSTALLPROPERTY_INSTALLLOCATION, location, ref length); int error = Marshal.GetLastWin32Error(); if (hr == 0) { path = location.ToString(); } else { Debug.WriteLine("Error loading install directory: " + error.ToString(CultureInfo.CurrentCulture)); } } catch { } if (string.IsNullOrEmpty(path)) { try { if (!getSDKDir) { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(ProductRootRegKey)) { if (key != null) path = (string)key.GetValue("InstallDir"); } } } catch { } } // if (string.IsNullOrEmpty(path)) path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); return path; } private static string GetInstallDirectory30() { string path = string.Empty; try { //ERROR_UNKNOWN_PROPERTY 1608L //ERROR_INVALID_PARAMETER 87L int length = FILENAME_MAX + 1; StringBuilder location = new StringBuilder(length); int hr = MsiGetProductInfoW(ProductCode, INSTALLPROPERTY_INSTALLLOCATION, location, ref length); int error = Marshal.GetLastWin32Error(); if (hr == 0) { path = location.ToString(); } else { Debug.WriteLine("Error loading 3.0 install directory: " + error.ToString(CultureInfo.CurrentCulture)); } } catch { } if (string.IsNullOrEmpty(path)) { try { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(ProductRootRegKey30)) { if (key != null) { path = (string)key.GetValue("InstallDir"); } } } catch { } } return path; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Type GetBaseType(PropertyInfo property, object owner, IServiceProvider serviceProvider) { //When we are emitting code for the dynamic properties we might get the propertyinfo as null if (owner == null) throw new ArgumentNullException("owner"); if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); if (property != null) { IDynamicPropertyTypeProvider basetypeProvider = owner as IDynamicPropertyTypeProvider; if (basetypeProvider != null) { Type type = basetypeProvider.GetPropertyType(serviceProvider, property.Name); if (type != null) return type; } return property.PropertyType; } return null; } // [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static AccessTypes GetAccessType(PropertyInfo property, object owner, IServiceProvider serviceProvider) { //When we are emitting code for the dynamic properties we might get the propertyinfo as null if (owner == null) throw new ArgumentNullException("owner"); if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); if (property != null) { IDynamicPropertyTypeProvider basetypeProvider = owner as IDynamicPropertyTypeProvider; if (basetypeProvider != null) return basetypeProvider.GetAccessType(serviceProvider, property.Name); } return AccessTypes.Read; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool IsChildActivity(CompositeActivity parent, Activity activity) { foreach (Activity containedActivity in parent.Activities) { if (activity == containedActivity) return true; if (containedActivity is CompositeActivity && Helpers.IsChildActivity(containedActivity as CompositeActivity, activity)) return true; } return false; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool TypesEqual(CodeTypeReference typeLeft, Type typeRight) { if (typeRight.IsArray && typeLeft.ArrayRank != typeRight.GetArrayRank()) return false; // if (!typeLeft.BaseType.Equals(typeRight.FullName)) return false; if (typeLeft.ArrayRank > 0) return TypesEqual(typeLeft.ArrayElementType, typeRight.GetElementType()); return true; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool TypesEqual(CodeTypeReference typeLeft, CodeTypeReference typeRight) { if (typeLeft.ArrayRank != typeRight.ArrayRank) return false; if (!typeLeft.BaseType.Equals(typeRight.BaseType)) return false; if (typeLeft.ArrayRank > 0) return TypesEqual(typeLeft.ArrayElementType, typeRight.ArrayElementType); return true; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static DesignerSerializationVisibility GetSerializationVisibility(MemberInfo memberInfo) { if (memberInfo == null) throw new ArgumentNullException("memberInfo"); DesignerSerializationVisibility designerSerializationVisibility = DesignerSerializationVisibility.Visible; // Calling GetCustomAttributes on PropertyInfo or EventInfo when the inherit parameter of GetCustomAttributes // is true does not walk the type hierarchy. But System.Attribute.GetCustomAttributes causes perf issues. object[] attributes = memberInfo.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true); if (attributes.Length > 0) designerSerializationVisibility = (attributes[0] as DesignerSerializationVisibilityAttribute).Visibility; else if (Attribute.IsDefined(memberInfo, typeof(DesignerSerializationVisibilityAttribute))) designerSerializationVisibility = (Attribute.GetCustomAttribute(memberInfo, typeof(DesignerSerializationVisibilityAttribute)) as DesignerSerializationVisibilityAttribute).Visibility; return designerSerializationVisibility; } // Method parameters must match exactly // [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static MethodInfo GetMethodExactMatch(Type type, string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) { MethodInfo foundMethod = null; MethodInfo[] methods = type.GetMethods(bindingAttr); foreach (MethodInfo method in methods) { bool matchName = ((bindingAttr & BindingFlags.IgnoreCase) == BindingFlags.IgnoreCase) ? string.Compare(method.Name, name, StringComparison.OrdinalIgnoreCase) == 0 : string.Compare(method.Name, name, StringComparison.Ordinal) == 0; if (matchName) { bool mismatch = false; if (types != null) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.GetLength(0) == types.Length) { for (int index = 0; !mismatch && index < parameters.Length; index++) mismatch = (parameters[index].ParameterType == null) || (!parameters[index].ParameterType.IsAssignableFrom(types[index])); } else mismatch = true; } if (!mismatch) { foundMethod = method; break; } } } return foundMethod; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static T GetAttributeFromObject(object attributeObject) where T : Attribute { if (attributeObject is AttributeInfoAttribute) return (T)((AttributeInfoAttribute)attributeObject).AttributeInfo.CreateAttribute(); if (attributeObject is T) return (T)attributeObject; return null; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Type GetDelegateFromEvent(EventInfo eventInfo) { if (eventInfo.EventHandlerType != null) return eventInfo.EventHandlerType; return TypeProvider.GetEventHandlerType(eventInfo); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void AddTypeProviderAssembliesFromRegistry(TypeProvider typeProvider, IServiceProvider serviceProvider) { if (typeProvider == null) throw new ArgumentNullException("typeProvider"); if (serviceProvider == null) throw new ArgumentNullException("serviceProvider"); RegistryKey referenceKey = Registry.CurrentUser.OpenSubKey(TypeProviderRegistryKeyPath); if (referenceKey != null) { ITypeProviderCreator typeProviderCreator = serviceProvider.GetService(typeof(ITypeProviderCreator)) as ITypeProviderCreator; foreach (string assemblyName in ((string[])referenceKey.GetValue(TypeProviderAssemblyRegValueName))) { try { if (typeProviderCreator != null) { bool addAssembly = true; Assembly assembly = typeProviderCreator.GetTransientAssembly(AssemblyName.GetAssemblyName(assemblyName)); // Check to see if a copy of the assembly is already added. if (assembly != null) { foreach (Type type in assembly.GetTypes()) { if (typeProvider.GetType(type.AssemblyQualifiedName) != null) addAssembly = false; break; } if (addAssembly) typeProvider.AddAssembly(assembly); } } else // AddAssemblyReference should take care of duplicates. typeProvider.AddAssemblyReference(assemblyName); } catch { // Continue loading. } } referenceKey.Close(); } } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void UpdateTypeProviderAssembliesRegistry(string assemblyName) { RegistryKey referenceKey = Registry.CurrentUser.CreateSubKey(TypeProviderRegistryKeyPath); if (referenceKey != null) { try { ArrayList references = null; if (referenceKey.ValueCount > 0) references = new ArrayList((string[])referenceKey.GetValue(TypeProviderAssemblyRegValueName)); else references = new ArrayList(); if (!references.Contains(assemblyName)) { references.Add(assemblyName); referenceKey.SetValue(TypeProviderAssemblyRegValueName, ((string[])references.ToArray(typeof(string)))); } } catch { //We eat the exception } finally { referenceKey.Close(); } } } internal static CompositeActivity GetDeclaringActivity(Activity activity) { if (activity == null) throw new ArgumentNullException("activity"); CompositeActivity parent = activity.Parent; while (parent != null) { // This will be the root if (parent.Parent == null) return parent; // Any custom activity found is the declaring activity if (IsCustomActivity(parent)) return parent; parent = parent.Parent; } return null; } internal static bool IsActivityLocked(Activity activity) { if (activity == null) throw new ArgumentNullException("activity"); CompositeActivity parent = activity.Parent; while (parent != null) { // If root, not locked if (parent.Parent == null) return false; // Any custom activity found, then locked if (IsCustomActivity(parent)) return true; parent = parent.Parent; } return false; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity GetEnclosingActivity(Activity activity) { Activity enclosingActivity; if (IsActivityLocked(activity)) enclosingActivity = Helpers.GetDeclaringActivity(activity); else enclosingActivity = GetRootActivity(activity); return enclosingActivity; } // This function returns all the executable activities including secondary flow activities. [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] public static IList GetAllEnabledActivities(CompositeActivity compositeActivity) { if (compositeActivity == null) throw new ArgumentNullException("compositeActivity"); List allActivities = new List(compositeActivity.EnabledActivities); foreach (Activity childActivity in compositeActivity.Activities) { if (childActivity.Enabled && IsFrameworkActivity(childActivity)) allActivities.Add(childActivity); } return allActivities; } public static bool IsFrameworkActivity(Activity activity) { return (activity is CancellationHandlerActivity || activity is CompensationHandlerActivity || activity is FaultHandlersActivity); } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static MethodInfo GetInterfaceMethod(Type interfaceType, string methodName) { MethodInfo methodInfo = null; string interfaceName = String.Empty; string method = String.Empty; if (methodName.LastIndexOf('.') > 0) { interfaceName = methodName.Substring(0, methodName.LastIndexOf('.')); method = methodName.Substring(methodName.LastIndexOf('.') + 1); } if (!String.IsNullOrEmpty(interfaceName)) { foreach (Type inheritedInterface in interfaceType.GetInterfaces()) { if (String.Compare(inheritedInterface.FullName, interfaceName, StringComparison.Ordinal) == 0) { methodInfo = inheritedInterface.GetMethod(method); break; } } } else { methodInfo = interfaceType.GetMethod(methodName); } return methodInfo; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static XmlWriter CreateXmlWriter(object output) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = ("\t"); settings.OmitXmlDeclaration = true; settings.CloseOutput = true; if (output is string) return XmlWriter.Create(output as string, settings); else if (output is TextWriter) return XmlWriter.Create(output as TextWriter, settings); else { Debug.Assert(false, "Invalid argument type. 'output' must either be string or TextWriter."); return null; } } #region DesignTimeType Support [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static string GetDesignTimeTypeName(object owner, object key) { string typeName = null; DependencyObject dependencyObject = owner as DependencyObject; if (dependencyObject != null && key != null) { if (dependencyObject.UserData.Contains(UserDataKeys.DesignTimeTypeNames)) { Hashtable typeNames = dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable; if (typeNames != null && typeNames.ContainsKey(key)) typeName = typeNames[key] as string; } } return typeName; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void SetDesignTimeTypeName(object owner, object key, string value) { DependencyObject dependencyObject = owner as DependencyObject; if (dependencyObject != null && key != null) { if (!dependencyObject.UserData.Contains(UserDataKeys.DesignTimeTypeNames)) dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] = new Hashtable(); Hashtable typeNames = dependencyObject.UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable; typeNames[key] = value; } } #endregion #region Helpers from ExecutableCompModHelpers // This only works for composite activity. [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool IsCustomActivity(CompositeActivity compositeActivity) { if (compositeActivity == null) throw new ArgumentNullException("compositeActivity"); if (compositeActivity.UserData.Contains(UserDataKeys.CustomActivity)) { return (bool)(compositeActivity.UserData[UserDataKeys.CustomActivity]); } else { try { CompositeActivity activity = Activator.CreateInstance(compositeActivity.GetType()) as CompositeActivity; if (activity != null && activity.Activities.Count > 0) { compositeActivity.UserData[UserDataKeys.CustomActivityDefaultName] = activity.Name; compositeActivity.UserData[UserDataKeys.CustomActivity] = true; // return true; } } catch { // } } compositeActivity.UserData[UserDataKeys.CustomActivity] = false; // return false; } [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "IndexOf(\".\") not a security issue.")] [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity ParseActivity(Activity parsingContext, string activityName) { if (parsingContext == null) throw new ArgumentNullException("parsingContext"); if (activityName == null) throw new ArgumentNullException("activityName"); string currentAtivityName = activityName; string nextActivityName = string.Empty; int indexOfDot = activityName.IndexOf("."); if (indexOfDot != -1) { currentAtivityName = activityName.Substring(0, indexOfDot); nextActivityName = activityName.Substring(indexOfDot + 1); if (nextActivityName.Length == 0) return null; } Activity currentActivity = GetActivity(parsingContext, currentAtivityName); if (currentActivity != null) { if (nextActivityName.Length > 0) { if (!(currentActivity is CompositeActivity) || !IsCustomActivity(currentActivity as CompositeActivity)) // current activity must be a custom activity, otherwise there should be no dots in the name. return null; string[] names = nextActivityName.Split('.'); for (int i = 0; i < names.Length; i++) { Activity nextActivity = GetActivity(currentActivity, names[i]); if (nextActivity == null || !Helpers.IsActivityLocked(nextActivity)) return null; CompositeActivity declaringActivity = GetDeclaringActivity(nextActivity); if (currentActivity != declaringActivity) return null; currentActivity = nextActivity; } return currentActivity; } else { // This activity should always be unlocked, unless if GetChildActivity() is called from // within the custom activity's companion class, then we don't have the full qualified ID available // at that time. We allow this to succeed only if the declaring activity is the same as the declaring // activity of the context activity passed in. if (Helpers.IsActivityLocked(currentActivity))//.IsLocked) { if (!IsDeclaringActivityMatchesContext(currentActivity, parsingContext)) return null; } return currentActivity; } } return null; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static Activity ParseActivityForBind(Activity context, string activityName) { if (context == null) throw new ArgumentNullException("context"); if (activityName == null) throw new ArgumentNullException("activityName"); if (string.Equals(activityName, "/Self", StringComparison.Ordinal)) { return context; } else if (activityName.StartsWith("/Parent", StringComparison.OrdinalIgnoreCase)) { Activity activity = context; string[] paths = activityName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < paths.Length && activity != null; i++) { string parent = paths[i].Trim(); activity = (string.Equals(parent, "Parent", StringComparison.OrdinalIgnoreCase)) ? activity.Parent : null; } return activity; } else if (Helpers.IsActivityLocked(context)) { // Look for the matching activity inside the custom activity context first. This is because if a bind // is coming from a custom activity, it's activity ref ID may not match the qualified ID of the // the activity. Activity activity = null; Activity declaringActivity = Helpers.GetDeclaringActivity(context); Guid currentContextGuid = GetRuntimeContextGuid(context); Guid declaringContextGuid = GetRuntimeContextGuid(declaringActivity); Activity currentContextActivity = context; Activity parentContextActivity = context.Parent; Guid parentContextGuid = GetRuntimeContextGuid(parentContextActivity); while (activity == null && declaringContextGuid != currentContextGuid) { // WinOE while (parentContextActivity != null && parentContextGuid == currentContextGuid) { currentContextActivity = parentContextActivity; parentContextActivity = parentContextActivity.Parent; parentContextGuid = GetRuntimeContextGuid(parentContextActivity); } activity = Helpers.ParseActivity(currentContextActivity, activityName); currentContextGuid = parentContextGuid; } if (activity == null) { // Check the declaring activity activity = Helpers.ParseActivity(declaringActivity, activityName); } // Nothing found, let's see if this is bind to the custom activity itself. if (activity == null) { if (!declaringActivity.UserData.Contains(UserDataKeys.CustomActivityDefaultName)) { //we need to activate a new instance of the declaringActivity's type and check if its name equals to the one we are looking for Activity newCustomActivity = Activator.CreateInstance(declaringActivity.GetType()) as Activity; declaringActivity.UserData[UserDataKeys.CustomActivityDefaultName] = newCustomActivity.Name; } if (((string)declaringActivity.UserData[UserDataKeys.CustomActivityDefaultName]) == activityName) activity = declaringActivity; } // if this is a locked activity, its bind reference must be within its declaring activity. We should not try // to resolve it beyond that scope. return activity; } Activity targetActivity = null; Activity parentActivity = context; //if it's a custom activity and it has parent, start looking for the target activity at the parent level //otherwise we'll get children of the custom activity bool mayLookInside = false; //we may look inside the custom activity if the target is not found outside CompositeActivity compositeParentActivity = parentActivity as CompositeActivity; if (compositeParentActivity != null && parentActivity.Parent != null && IsCustomActivity(compositeParentActivity)) { mayLookInside = true; parentActivity = parentActivity.Parent; } while (targetActivity == null && parentActivity != null) { targetActivity = parentActivity.GetActivityByName(activityName, true); parentActivity = parentActivity.Parent; } if (mayLookInside && targetActivity == null) { //if we have not found an appropriate activity at the parent level, try looking inside //we dont need to look outside (loop while parent is not null) - it has already been done above parentActivity = context; targetActivity = parentActivity.GetActivityByName(activityName, true); } return (targetActivity == null) ? Helpers.ParseActivity(Helpers.GetRootActivity(context), activityName) : targetActivity; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private static Guid GetRuntimeContextGuid(Activity currentActivity) { Activity contextActivity = currentActivity; Guid contextGuid = (Guid)contextActivity.GetValue(Activity.ActivityContextGuidProperty); while (contextGuid == Guid.Empty && contextActivity.Parent != null) { contextActivity = contextActivity.Parent; contextGuid = (Guid)contextActivity.GetValue(Activity.ActivityContextGuidProperty); } return contextGuid; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private static bool IsDeclaringActivityMatchesContext(Activity currentActivity, Activity context) { CompositeActivity declaringContext = context as CompositeActivity; CompositeActivity declaringActivityOfCurrent = Helpers.GetDeclaringActivity(currentActivity); // If the context activity is locked and it is a primitive activity // or NOT a custom activity then we need to find its enclosing // custom activity. if (Helpers.IsActivityLocked(context) && (declaringContext == null || !Helpers.IsCustomActivity(declaringContext)) ) declaringContext = Helpers.GetDeclaringActivity(context); if (declaringContext == declaringActivityOfCurrent) return true; else return false; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static bool IsAlternateFlowActivity(Activity activity) { if (activity == null) return false; bool isAlternateFlowActivityAttribute = false; //dont want to use reflection to check for the alternate flow attribute //this is a fix for a perf issue - use of reflection in a ui loop if (!activity.UserData.Contains(typeof(AlternateFlowActivityAttribute))) { isAlternateFlowActivityAttribute = activity.GetType().GetCustomAttributes(typeof(AlternateFlowActivityAttribute), true).Length != 0; activity.UserData[typeof(AlternateFlowActivityAttribute)] = isAlternateFlowActivityAttribute; } else { isAlternateFlowActivityAttribute = (bool)activity.UserData[typeof(AlternateFlowActivityAttribute)]; } return isAlternateFlowActivityAttribute; } [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] private static Activity GetActivity(Activity containerActivity, string id) { if (containerActivity != null) { Queue activities = new Queue(); activities.Enqueue(containerActivity); while (activities.Count > 0) { Activity activity = (Activity)activities.Dequeue(); if (activity.Enabled) { if (activity.Name == id) return activity; if (activity is CompositeActivity) { foreach (Activity child in ((CompositeActivity)activity).Activities) activities.Enqueue(child); } } } } return null; } #endregion } #endregion #region Class TypeDescriptorContext (SHARED WITH ACTIVITIES, ORCHESTRATIONDESIGNER) [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Not all assemblies that include this file instantiate the class.")] internal sealed class TypeDescriptorContext : ITypeDescriptorContext { private IServiceProvider serviceProvider; private PropertyDescriptor propDesc; private object instance; public TypeDescriptorContext(IServiceProvider serviceProvider, PropertyDescriptor propDesc, object instance) { this.serviceProvider = serviceProvider; this.propDesc = propDesc; this.instance = instance; } public IContainer Container { get { return (IContainer)this.serviceProvider.GetService(typeof(IContainer)); } } public object Instance { get { return this.instance; } } public PropertyDescriptor PropertyDescriptor { get { return this.propDesc; } } public object GetService(Type serviceType) { return this.serviceProvider.GetService(serviceType); } public bool OnComponentChanging() { IComponentChangeService componentChangeService = (IComponentChangeService)this.serviceProvider.GetService(typeof(IComponentChangeService)); if (componentChangeService != null) { try { componentChangeService.OnComponentChanging(this.instance, this.propDesc); } catch (CheckoutException ce) { if (ce == CheckoutException.Canceled) return false; throw ce; } } return true; } public void OnComponentChanged() { IComponentChangeService componentChangeService = (IComponentChangeService)this.serviceProvider.GetService(typeof(IComponentChangeService)); if (componentChangeService != null) componentChangeService.OnComponentChanged(this.instance, this.propDesc, null, null); } } #endregion // This class has been added as a fix for internal static class DebuggerHelpers { [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", Justification = "IndexOf(\".\") not a security issue.")] internal static Activity ParseActivity(Activity parsingContext, string activityName) { if (parsingContext == null) throw new ArgumentNullException("parsingContext"); if (activityName == null) throw new ArgumentNullException("activityName"); string currentAtivityName = activityName; string nextActivityName = string.Empty; int indexOfDot = activityName.IndexOf("."); if (indexOfDot != -1) { currentAtivityName = activityName.Substring(0, indexOfDot); nextActivityName = activityName.Substring(indexOfDot + 1); if (nextActivityName.Length == 0) return null; } Activity currentActivity = null; currentActivity = GetActivity(parsingContext, currentAtivityName); // The check for parsingContext.Parent != null is added here because IsCustomActivity returns true for root activities. if (currentActivity == null && (parsingContext is CompositeActivity) && parsingContext.Parent != null && Helpers.IsCustomActivity(parsingContext as CompositeActivity)) currentActivity = GetActivity(parsingContext, parsingContext.QualifiedName + "." + currentAtivityName); if (currentActivity != null) { if (nextActivityName.Length > 0) { if (!(currentActivity is CompositeActivity) || !Helpers.IsCustomActivity(currentActivity as CompositeActivity)) // current activity must be a custom activity, otherwise there should be no dots in the name. return null; string[] names = nextActivityName.Split('.'); for (int i = 0; i < names.Length; i++) { Activity nextActivity = GetActivity(currentActivity, currentActivity.QualifiedName + "." + names[i]); if (nextActivity == null || !Helpers.IsActivityLocked(nextActivity)) return null; CompositeActivity declaringActivity = Helpers.GetDeclaringActivity(nextActivity); if (currentActivity != declaringActivity) return null; currentActivity = nextActivity; } return currentActivity; } else { // This activity should always be unlocked, unless if GetChildActivity() is called from // within the custom activity's companion class, then we don't have the full qualified ID available // at that time. We allow this to succeed only if the declaring activity is the same as the declaring // activity of the context activity passed in. if (Helpers.IsActivityLocked(currentActivity))//.IsLocked) { if (!IsDeclaringActivityMatchesContext(currentActivity, parsingContext)) return null; } return currentActivity; } } return null; } private static Activity GetActivity(Activity containerActivity, string id) { if (containerActivity != null) { Queue activities = new Queue(); activities.Enqueue(containerActivity); while (activities.Count > 0) { Activity activity = (Activity)activities.Dequeue(); if (activity.Enabled) { if (activity.QualifiedName == id) return activity; if (activity is CompositeActivity) { foreach (Activity child in ((CompositeActivity)activity).Activities) activities.Enqueue(child); } } } } return null; } private static bool IsDeclaringActivityMatchesContext(Activity currentActivity, Activity context) { CompositeActivity declaringContext = context as CompositeActivity; CompositeActivity declaringActivityOfCurrent = Helpers.GetDeclaringActivity(currentActivity); // If the context activity is locked and it is a primitive activity // or NOT a custom activity then we need to find its enclosing // custom activity. if (Helpers.IsActivityLocked(context) && (declaringContext == null || !Helpers.IsCustomActivity(declaringContext)) ) declaringContext = Helpers.GetDeclaringActivity(context); if (declaringContext == declaringActivityOfCurrent) return true; else return false; } } }