/// <summary> /// Compiles the method for the subscription and returns the function. /// </summary> /// <param name="methodBodyString">String containing the method body to compile</param> /// <param name="usingLibraries">List of the using libraries by the expression</param> /// <param name="referencedAssemblies">List of the reference assemblies used by the expression</param> /// <param name="filterMethod">The compiled function</param> /// <param name="results">Compiler results</param> /// <returns>true if successful, false if failed</returns> public static bool CompileFilterMethod(string methodBodyString, List <string> usingLibraries, List <string> referencedAssemblies, out WspFilterMethod filterMethod, out CompilerResults results) { Dictionary <string, string> usingDictionary = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase); Dictionary <string, string> referencedDictionary = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase); filterMethod = null; results = null; string className = "a" + Guid.NewGuid().ToString().Replace('-', 'a'); try { usingDictionary[@"using System;"] = null; usingDictionary[@"using System.Linq;"] = null; usingDictionary[@"using System.Linq.Expressions;"] = null; usingDictionary[@"using Microsoft.WebSolutionsPlatform.Event;"] = null; usingDictionary[@"using Microsoft.WebSolutionsPlatform.PubSubManager;"] = null; if (usingLibraries != null) { for (int i = 0; i < usingLibraries.Count; i++) { if (usingLibraries[i].EndsWith(";") == true) { usingDictionary[usingLibraries[i]] = null; } else { usingDictionary[usingLibraries[i] + ";"] = null; } } } referencedDictionary[@"System.dll"] = null; referencedDictionary[@"System.Core.dll"] = null; referencedDictionary[AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"WspEvent.dll"] = null; referencedDictionary[AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"WspPubSubMgr.dll"] = null; if (referencedAssemblies != null) { for (int i = 0; i < referencedAssemblies.Count; i++) { referencedDictionary[referencedAssemblies[i]] = null; } } string[] code = new string[1]; StringBuilder sb = new StringBuilder(); foreach (string s in usingDictionary.Keys) { sb.Append(s + "\n"); } sb.Append("public class " + className + "\n"); sb.Append("{\n"); sb.Append(" public WspFilterMethod GetFilterFunction()\n"); sb.Append(" {\n"); sb.Append(" return FilterMethod;\n"); sb.Append(" }\n"); sb.Append("\n"); sb.Append(" public bool FilterMethod(WspEvent wspEvent)\n"); sb.Append(" {\n"); sb.Append(methodBodyString); sb.Append(" }\n"); sb.Append("}\n"); code[0] = sb.ToString(); CSharpCodeProvider compiler = new CSharpCodeProvider(); CompilerParameters parms = new System.CodeDom.Compiler.CompilerParameters { GenerateExecutable = false, GenerateInMemory = true }; foreach (string asm in referencedDictionary.Keys) { parms.ReferencedAssemblies.Add(asm); } results = compiler.CompileAssemblyFromSource(parms, code); if (results.Errors.HasErrors == true) { return(false); } else { var wspFilterClass = results.CompiledAssembly.CreateInstance(className); Type filterType = wspFilterClass.GetType(); MethodInfo tempMethod = filterType.GetMethod("GetFilterFunction"); ConstructorInfo filterConstructor = filterType.GetConstructor(Type.EmptyTypes); object filterObject = filterConstructor.Invoke(new object[] { }); filterMethod = (WspFilterMethod)tempMethod.Invoke(filterObject, new object[] { }); WspEvent wspEvent = new WspEvent(Guid.Empty, null, null); filterMethod(wspEvent); return(true); } } catch { return(false); } }
/// <summary> /// The ObservableSubscription constructor is used to create an observable filtered subscription to then subscribe to via Rx /// </summary> /// <remarks> /// The method will obviously consume more overhead, so only use when necessary. If referenced assemblies, they must be /// deployed and accessible by the WspEventRouter on ALL computers running Wsp. /// </remarks> /// <param name="eventType">The event type to subscribe to</param> /// <param name="localOnly">True if only local events are to be subscribed to</param> /// <param name="methodBody">Method body defining the filter</param> /// <param name="usingLibraries">List of using libraries which the method requires, null if none required</param> /// <param name="referencedAssemblies">List of referenced assemblies which the method requires, null if none required</param> public WspEventObservable(Guid eventType, bool localOnly, string methodBody, List <string> usingLibraries, List <string> referencedAssemblies) { this.id = Guid.NewGuid(); this.eventType = eventType; this.localOnly = localOnly; this.usingLibraries = null; this.referencedAssemblies = null; this.filterMethod = null; if (string.IsNullOrEmpty(methodBody) == true) { this.methodBody = string.Empty; } else { this.methodBody = methodBody; if (usingLibraries != null) { this.usingLibraries = new List <string>(usingLibraries.Count); for (int i = 0; i < usingLibraries.Count; i++) { this.usingLibraries[i] = usingLibraries[i]; } } if (referencedAssemblies != null) { this.referencedAssemblies = new List <string>(referencedAssemblies.Count); for (int i = 0; i < referencedAssemblies.Count; i++) { this.referencedAssemblies[i] = referencedAssemblies[i]; } } CompilerResults results; bool rc = CompileFilterMethod(this.methodBody, this.usingLibraries, this.referencedAssemblies, out this.filterMethod, out results); if (rc == false) { throw new PubSubCompileException(results.Errors.ToString()); } } eventQueueCounter = new PerformanceCounter(); eventQueueCounter.InstanceLifetime = PerformanceCounterInstanceLifetime.Process; eventQueueCounter.CategoryName = "WspEventRouterApplication"; eventQueueCounter.CounterName = "SubscriptionQueueSize"; eventQueueCounter.InstanceName = "PID" + Process.GetCurrentProcess().Id.ToString() + ":" + eventType.ToString() + ":" + Guid.NewGuid().ToString().GetHashCode().ToString(); eventQueueCounter.ReadOnly = false; this.queue = new SynchronizationQueueGeneric <WspEvent>(eventQueueCounter, eventType); observableThread = new Thread(ObservableThread); observableThread.Start(); lock (lockObj) { if (wspSubscriptionThread == null) { wspSubscriptionManager = new SubscriptionManager(); wspSubscriptionThread = new Thread(wspSubscriptionManager.Listener); wspSubscriptionThread.Start(); } } }