1 // --------------------------------------------------------------------------- 2 // Copyright (C) 2006 Microsoft Corporation All Rights Reserved 3 // --------------------------------------------------------------------------- 4 5 #define CODE_ANALYSIS 6 using System.CodeDom; 7 using System.Collections; 8 using System.ComponentModel.Design.Serialization; 9 using System.Diagnostics.CodeAnalysis; 10 using System.Globalization; 11 using System.IO; 12 using System.Workflow.ComponentModel; 13 using System.Workflow.ComponentModel.Compiler; 14 using System.Workflow.ComponentModel.Design; 15 using System.Workflow.ComponentModel.Serialization; 16 using System.Xml; 17 using System.Reflection; 18 using System.Diagnostics; 19 using System.Workflow.Activities.Common; 20 21 namespace System.Workflow.Activities.Rules 22 { 23 internal static class ConditionHelper 24 { GetContextType(ITypeProvider typeProvider, Activity currentActivity)25 internal static Type GetContextType(ITypeProvider typeProvider, Activity currentActivity) 26 { 27 Type contextType = null; 28 string className = String.Empty; 29 Activity rootActivity = null; 30 31 if (Helpers.IsActivityLocked(currentActivity)) 32 { 33 rootActivity = Helpers.GetDeclaringActivity(currentActivity); 34 } 35 else 36 { 37 rootActivity = Helpers.GetRootActivity(currentActivity); 38 } 39 40 if (rootActivity != null) 41 { 42 className = rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string; 43 if (!String.IsNullOrEmpty(className)) 44 contextType = typeProvider.GetType(className, false); 45 46 if (contextType == null) 47 contextType = typeProvider.GetType(rootActivity.GetType().FullName); 48 49 // If all else fails (likely, we don't have a type provider), it's the root activity type. 50 if (contextType == null) 51 contextType = rootActivity.GetType(); 52 } 53 54 return contextType; 55 } 56 57 /// <summary> 58 /// Is type a nullable value type (e.g. double?)? 59 /// </summary> 60 /// <param name="type"></param> 61 /// <returns></returns> IsNullableValueType(Type type)62 internal static bool IsNullableValueType(Type type) 63 { 64 return ((type.IsValueType) && (type.IsGenericType) && (type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))); 65 } 66 67 /// <summary> 68 /// Is type a standard value type (i.e. not Nullable)? 69 /// </summary> 70 /// <param name="type"></param> 71 /// <returns></returns> IsNonNullableValueType(Type type)72 internal static bool IsNonNullableValueType(Type type) 73 { 74 return ((type.IsValueType) && (!type.IsGenericType) && (type != typeof(string))); 75 } 76 CloneObject(object original)77 internal static object CloneObject(object original) 78 { 79 if (original == null) 80 return null; 81 82 if (original.GetType().IsValueType) 83 return original; 84 85 ICloneable cloneable = original as ICloneable; 86 if (cloneable != null) 87 return cloneable.Clone(); 88 89 string message = string.Format(CultureInfo.CurrentCulture, Messages.NotCloneable, original.GetType().FullName); 90 throw new NotSupportedException(message); 91 } 92 CloneUserData(CodeObject original, CodeObject result)93 internal static void CloneUserData(CodeObject original, CodeObject result) 94 { 95 // clone UserData, if possible 96 foreach (object key in original.UserData.Keys) 97 { 98 object newKey = CloneObject(key); 99 object newValue = CloneObject(original.UserData[key]); 100 result.UserData.Add(newKey, newValue); 101 } 102 } 103 104 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] Load_Rules_DT(IServiceProvider serviceProvider, DependencyObject activity)105 internal static RuleDefinitions Load_Rules_DT(IServiceProvider serviceProvider, DependencyObject activity) 106 { 107 RuleDefinitions rules = (RuleDefinitions)activity.GetValue(RuleDefinitions.RuleDefinitionsProperty); 108 if (rules == null) 109 { 110 WorkflowDesignerLoader loader = (WorkflowDesignerLoader)serviceProvider.GetService(typeof(WorkflowDesignerLoader)); 111 if (loader != null) 112 { 113 string rulesFileName = string.Empty; 114 if (!string.IsNullOrEmpty(loader.FileName)) 115 rulesFileName = Path.Combine(Path.GetDirectoryName(loader.FileName), Path.GetFileNameWithoutExtension(loader.FileName)); 116 rulesFileName += ".rules"; 117 118 try 119 { 120 using (TextReader ruleFileReader = loader.GetFileReader(rulesFileName)) 121 { 122 if (ruleFileReader == null) 123 { 124 rules = new RuleDefinitions(); 125 } 126 else 127 { 128 using (XmlReader xmlReader = XmlReader.Create(ruleFileReader)) 129 rules = new WorkflowMarkupSerializer().Deserialize(xmlReader) as RuleDefinitions; 130 } 131 } 132 } 133 catch (Exception) 134 { 135 rules = new RuleDefinitions(); 136 // 137 } 138 } 139 activity.SetValue(RuleDefinitions.RuleDefinitionsProperty, rules); 140 } 141 return rules; 142 } 143 Flush_Rules_DT(IServiceProvider serviceProvider, Activity activity)144 internal static void Flush_Rules_DT(IServiceProvider serviceProvider, Activity activity) 145 { 146 RuleDefinitions rules = (RuleDefinitions)activity.GetValue(RuleDefinitions.RuleDefinitionsProperty); 147 if (rules != null) 148 { 149 WorkflowDesignerLoader loader = (WorkflowDesignerLoader)serviceProvider.GetService(typeof(WorkflowDesignerLoader)); 150 if (loader != null) 151 { 152 string rulesFileName = string.Empty; 153 if (!string.IsNullOrEmpty(loader.FileName)) 154 rulesFileName = Path.Combine(Path.GetDirectoryName(loader.FileName), Path.GetFileNameWithoutExtension(loader.FileName)); 155 rulesFileName += ".rules"; 156 157 using (TextWriter ruleFileWriter = loader.GetFileWriter(rulesFileName)) 158 { 159 if (ruleFileWriter != null) 160 { 161 using (XmlWriter xmlWriter = Helpers.CreateXmlWriter(ruleFileWriter)) 162 { 163 DesignerSerializationManager designerSerializationManager = new DesignerSerializationManager(serviceProvider); 164 using (designerSerializationManager.CreateSession()) 165 { 166 new WorkflowMarkupSerializer().Serialize(designerSerializationManager, xmlWriter, rules); 167 } 168 } 169 170 } 171 } 172 } 173 } 174 } 175 Load_Rules_RT(Activity declaringActivity)176 internal static RuleDefinitions Load_Rules_RT(Activity declaringActivity) 177 { 178 RuleDefinitions rules = declaringActivity.GetValue(RuleDefinitions.RuleDefinitionsProperty) as RuleDefinitions; 179 if (rules == null) 180 { 181 rules = ConditionHelper.GetRuleDefinitionsFromManifest(declaringActivity.GetType()); 182 if (rules != null) 183 declaringActivity.SetValue(RuleDefinitions.RuleDefinitionsProperty, rules); 184 } 185 return rules; 186 } 187 188 // To improve performance, cache the RuleDefinitions deserialized from 189 // .rules resources keyed by the type of activity. 190 static Hashtable cloneableOrNullRulesResources = new Hashtable(); 191 // It is unfortunate, however, that cloning might not always succeed, we will keep them here. 192 static Hashtable uncloneableRulesResources = new Hashtable(); 193 GetRuleDefinitionsFromManifest(Type workflowType)194 internal static RuleDefinitions GetRuleDefinitionsFromManifest(Type workflowType) 195 { 196 if (workflowType == null) 197 throw new ArgumentNullException("workflowType"); 198 199 RuleDefinitions rules = null; 200 201 if (cloneableOrNullRulesResources.ContainsKey(workflowType)) 202 { 203 rules = (RuleDefinitions)cloneableOrNullRulesResources[workflowType]; 204 if (rules != null) 205 { 206 // This should always succeed, since it is coming out of the cloneable cache 207 rules = rules.Clone(); 208 } 209 } 210 else 211 { 212 string resourceName = workflowType.Name + ".rules"; 213 Stream stream = workflowType.Module.Assembly.GetManifestResourceStream(workflowType, resourceName); 214 215 // Try just the .rules file name. This is needed for wfc.exe compilation scenarios. 216 if (stream == null) 217 stream = workflowType.Module.Assembly.GetManifestResourceStream(resourceName); 218 219 if (stream != null) 220 { 221 using (StreamReader reader = new StreamReader(stream)) 222 { 223 using (XmlReader xmlReader = XmlReader.Create(reader)) 224 rules = new WorkflowMarkupSerializer().Deserialize(xmlReader) as RuleDefinitions; 225 } 226 } 227 // Don't know yet whether 'rules' is cloneable, give it a try 228 if (!uncloneableRulesResources.ContainsKey(workflowType)) 229 { 230 try 231 { 232 RuleDefinitions originalRules = rules; 233 if (rules != null) 234 { 235 rules = rules.Clone(); 236 } 237 lock (cloneableOrNullRulesResources) 238 { 239 cloneableOrNullRulesResources[workflowType] = originalRules; 240 } 241 } 242 catch (Exception) 243 { 244 lock (uncloneableRulesResources) 245 { 246 uncloneableRulesResources[workflowType] = null; 247 } 248 } 249 } 250 } 251 return rules; 252 } 253 } 254 255 internal static class EnumHelper 256 { 257 [SuppressMessage("Microsoft.Performance", "CA1803:AvoidCostlyCallsWherePossible")] GetUnderlyingType(Type type)258 public static Type GetUnderlyingType(Type type) 259 { 260 Type underlyingType = typeof(int); 261 if (type.GetType().FullName.Equals("System.Workflow.ComponentModel.Compiler.DesignTimeType", StringComparison.Ordinal))// designTimeType = type as System.Workflow.ComponentModel.Compiler.DesignTimeType; 262 { 263 //this is a design time type, need to get the enum type data out of it 264 MethodInfo methodInfo = type.GetType().GetMethod("GetEnumType"); 265 Debug.Assert(methodInfo != null, "Missing GetEnumType method on the DesignTimeType!"); 266 if (methodInfo != null) 267 { 268 Type result = methodInfo.Invoke(type, new object[0]) as Type; 269 underlyingType = (result != null) ? result : underlyingType; 270 } 271 } 272 else 273 { 274 underlyingType = Enum.GetUnderlyingType(type); 275 } 276 277 return underlyingType; 278 } 279 } 280 } 281