From 7ed460a8eb5042ff0699f16bd7e1b19b77970f94 Mon Sep 17 00:00:00 2001 From: marcu Date: Mon, 5 Mar 2018 16:57:51 +0100 Subject: [PATCH 01/10] current state for code-review --- .../EnumerableExpressions/DebugVisitor.cs | 38 ++++ .../EnumerableExpressions/DmglVisualizer.cs | 132 ++++++++++++++ .../DynamicDependencyGraphDgmlVisualizer.cs | 162 ++++++++++++++++++ .../GroupJoinExpression.cs | 35 +++- .../EnumerableExpressions/JoinExpression.cs | 34 +++- .../EnumerableExpressions/QueryOptimizer.cs | 68 ++++++++ .../QueryOptimizerVisitor.cs | 35 ++++ .../EnumerableExpressions/SelectExpression.cs | 66 ++++++- .../SelectManyExpression.cs | 35 +++- .../Expressions.Linq/Expressions.Linq.csproj | 12 ++ .../Facade/IEnumerableExpression.cs | 19 ++ .../Facade/OptimizableExpressionExtensions.cs | 23 +++ .../NotifySystemTests.cs | 153 +++++++++++++++++ 13 files changed, 808 insertions(+), 4 deletions(-) create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs create mode 100644 Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs new file mode 100644 index 000000000..8c8c49658 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs @@ -0,0 +1,38 @@ +using System.Linq.Expressions; + +namespace NMF.Expressions +{ + public class DebugVisitor : ExpressionVisitor + { + private int level = 0; + + public override Expression Visit(Expression exp) + { + if (exp != null) + { + if (level == 0) + { + System.Diagnostics.Debug.WriteLine("#################################"); + } + + + for (int i = 0; i < level; i++) + { + System.Diagnostics.Debug.Write("   "); + } + System.Diagnostics.Debug.WriteLine("{0}  -  {1} : || {2} ||", + exp.NodeType, exp.GetType().Name, exp.ToString()); + } + level++; + Expression result = base.Visit(exp); + level--; + return result; + } + + public void Display(Expression exp) + { + System.Diagnostics.Debug.WriteLine("===== DisplayVisitor.Display ====="); + this.Visit(exp); + } + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs new file mode 100644 index 000000000..86d073739 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Security.Cryptography.X509Certificates; +using System.Xml.Linq; + +namespace NMF.Expressions +{ + public static class DmglVisualizer + { + public static XDocument Doc { get; set; } + + private static XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml"); + + private static int lastAddedNodeId; + + public static void Initialize() + { + Doc = CreateDgmlDoc(); + var nodes = Doc.Root.Element(ns + "Nodes"); + var links = Doc.Root.Element(ns + "Links"); + + lastAddedNodeId = 0; + } + + public static void AddNode(IEnumerableExpression node) + { + if(Doc == null) return; + var nodes = Doc.Root.Element(ns + "Nodes"); + var nodeToAdd = ToDgmlNode(node); + nodes.Add(nodeToAdd); + } + + private static XElement ToDgmlLink(IEnumerableExpression node) + { + var e = new XElement(ns + "Link"); + e.SetAttributeValue("Source", node.GetHashCode()); + e.SetAttributeValue("Target", lastAddedNodeId); + return e; + } + + private static XElement ToDgmlNode(IEnumerableExpression node) + { + var links = Doc.Root.Element(ns + "Links"); + + var e = new XElement(ns + "Node"); + + if (lastAddedNodeId != 0) + links.Add(ToDgmlLink(node)); + + lastAddedNodeId = node.GetHashCode(); + e.SetAttributeValue("Id", lastAddedNodeId); + e.SetAttributeValue("Label", NodeToLabel(node)); + + return e; + + } + + public static void OpenDgml() + { + OpenDgml(Doc); + } + + + private static XDocument CreateDgmlDoc() + { + var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + doc.Add(new XElement(ns + "DirectedGraph")); + doc.Root.SetAttributeValue("Layout", "Sugiyama"); + doc.Root.SetAttributeValue("GraphDirection", "BottomToTop"); + var nodes = new XElement(ns + "Nodes"); + doc.Root.Add(nodes); + var links = new XElement(ns + "Links"); + doc.Root.Add(links); + var categories = new XElement(ns + "Categories"); + doc.Root.Add(categories); + var potentialChangeSource = new XElement(ns + "Category"); + potentialChangeSource.SetAttributeValue("Id", "PotentialChangeSource"); + potentialChangeSource.SetAttributeValue("Background", "LightBlue"); + categories.Add(potentialChangeSource); + var actualChangeSource = new XElement(ns + "Category"); + actualChangeSource.SetAttributeValue("Id", "ActualChangeSource"); + actualChangeSource.SetAttributeValue("Background", "Green"); + actualChangeSource.SetAttributeValue("Stroke", "Green"); + actualChangeSource.SetAttributeValue("StrokeThickness", "3"); + categories.Add(actualChangeSource); + var syncNode = new XElement(ns + "Category"); + syncNode.SetAttributeValue("Id", "SyncNode"); + syncNode.SetAttributeValue("Background", "Red"); + categories.Add(syncNode); + return doc; + } + + private static void OpenDgml(XDocument doc) + { + var fileName = DateTime.Now.ToString("hh-mm-ss-ff") + ".dgml"; + var filePath = Path.Combine(Path.GetTempPath(), fileName); + doc.Save(filePath); + System.Diagnostics.Process.Start(filePath); + } + + + + private static string NodeToLabel(IEnumerableExpression node) + { + var typeName = node.GetType().Name; + var result = typeName.Replace("Observable", ""); + int genericIndex = result.IndexOf('`'); + if (genericIndex > 0) + result = result.Remove(genericIndex); + + var valueProp = node.GetType().GetProperties().FirstOrDefault(p => p.Name == "Value"); + if (valueProp != null) + result += "\nValue: " + valueProp.GetValue(node); + + var countProp = node.GetType().GetProperty("Count"); + if (countProp != null) + result += "\nCount: " + countProp.GetValue(node); + + return result; + } + + + + + } + + +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs new file mode 100644 index 000000000..9481298b4 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs @@ -0,0 +1,162 @@ +using NMF.Expressions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +//using TrainBenchmark; + +namespace NMF.Expressions.EnumerableExpressions +{ + public static class DDGDgmlVisualizer + { + private static XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml"); + + public static void initDgmlVisualizer(INotifyEnumerable func) + { + //var test = new SwitchSet(); + //var query = test.Data.Query; + var changeSources = Enumerable.Empty(); + + var doc = CreateDgml(func, changeSources); + OpenDgml(doc); + } + + private static XDocument CreateDgml(INotifiable query, IEnumerable changeSources) + { + var doc = CreateDgmlDoc(); + var nodes = doc.Root.Element(ns + "Nodes"); + var links = doc.Root.Element(ns + "Links"); + + var allNodes = new[] { query }.Concat(NMF.Utilities.Extensions.SelectRecursive(query, n => n.Dependencies)).ToList(); + foreach (var node in allNodes) + { + nodes.Add(ToDgmlNode(node)); + foreach (var link in ToDgmlLink(node)) + links.Add(link); + } + + var sourceNodesIds = changeSources.Select(n => n.GetHashCode().ToString()).ToList(); + var actualSources = nodes.Elements().Where(e => sourceNodesIds.Contains(e.Attribute("Id").Value)); + foreach (var s in actualSources) + s.SetAttributeValue("Category", "ActualChangeSource"); + + var syncNodes = FindSyncNodes(changeSources); + var syncNodesIds = syncNodes.Select(n => n.GetHashCode().ToString()).ToList(); + var syncs = nodes.Elements().Where(e => syncNodesIds.Contains(e.Attribute("Id").Value)); + foreach (var s in syncs) + s.SetAttributeValue("Category", "SyncNode"); + + foreach (var node in changeSources) + { + var path = NMF.Utilities.Extensions.SelectRecursive(node, n => n.Successors).ToList(); + for (int i = 0; i < path.Count - 1; i++) + { + var src = path[i]; + var dst = path[i + 1]; + var link = links.Elements().First(e => e.Attribute("Source").Value == src.GetHashCode().ToString() && e.Attribute("Target").Value == dst.GetHashCode().ToString()); + link.SetAttributeValue("Category", "ActualChangeSource"); + } + } + + return doc; + } + + private static void OpenDgml(XDocument doc) + { + var fileName = DateTime.Now.ToString("hh-mm-ss") + ".dgml"; + var filePath = Path.Combine(Path.GetTempPath(), fileName); + doc.Save(filePath); + System.Diagnostics.Process.Start(filePath); + } + + private static XDocument CreateDgmlDoc() + { + var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + doc.Add(new XElement(ns + "DirectedGraph")); + doc.Root.SetAttributeValue("Layout", "Sugiyama"); + doc.Root.SetAttributeValue("GraphDirection", "BottomToTop"); + var nodes = new XElement(ns + "Nodes"); + doc.Root.Add(nodes); + var links = new XElement(ns + "Links"); + doc.Root.Add(links); + var categories = new XElement(ns + "Categories"); + doc.Root.Add(categories); + var potentialChangeSource = new XElement(ns + "Category"); + potentialChangeSource.SetAttributeValue("Id", "PotentialChangeSource"); + potentialChangeSource.SetAttributeValue("Background", "LightBlue"); + categories.Add(potentialChangeSource); + var actualChangeSource = new XElement(ns + "Category"); + actualChangeSource.SetAttributeValue("Id", "ActualChangeSource"); + actualChangeSource.SetAttributeValue("Background", "Green"); + actualChangeSource.SetAttributeValue("Stroke", "Green"); + actualChangeSource.SetAttributeValue("StrokeThickness", "3"); + categories.Add(actualChangeSource); + var syncNode = new XElement(ns + "Category"); + syncNode.SetAttributeValue("Id", "SyncNode"); + syncNode.SetAttributeValue("Background", "Red"); + categories.Add(syncNode); + return doc; + } + + private static XElement ToDgmlNode(INotifiable node) + { + var e = new XElement(ns + "Node"); + e.SetAttributeValue("Id", node.GetHashCode()); + e.SetAttributeValue("Label", NodeToLabel(node)); + return e; + } + + private static string NodeToLabel(INotifiable node) + { + var typeName = node.GetType().Name; + var result = typeName.Replace("Observable", ""); + int genericIndex = result.IndexOf('`'); + if (genericIndex > 0) + result = result.Remove(genericIndex); + + var valueProp = node.GetType().GetProperties().FirstOrDefault(p => p.Name == "Value"); + if (valueProp != null) + result += "\nValue: " + valueProp.GetValue(node); + + var countProp = node.GetType().GetProperty("Count"); + if (countProp != null) + result += "\nCount: " + countProp.GetValue(node); + + return result; + } + + private static IEnumerable ToDgmlLink(INotifiable node) + { + return node.Dependencies.Select(d => + { + var e = new XElement(ns + "Link"); + e.SetAttributeValue("Source", d.GetHashCode()); + e.SetAttributeValue("Target", node.GetHashCode()); + return e; + }); + } + + private static List FindSyncNodes(IEnumerable sourceNodes) + { + var result = new List(); + var visited = new HashSet(); + var stack = new Stack(sourceNodes); + + while (stack.Any()) + { + var item = stack.Pop(); + visited.Add(item.GetHashCode()); + foreach (var suc in item.Successors) + stack.Push(suc); + + if (item.Dependencies.Count(d => visited.Contains(d.GetHashCode())) == 2) + result.Add(item); + } + + return result; + } + } +} diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index 05d8b6933..f74a3ec7c 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq.Expressions; using System.Text; using SL = System.Linq.Enumerable; @@ -7,7 +8,7 @@ namespace NMF.Expressions { - internal class GroupJoinExpression : IEnumerableExpression + internal class GroupJoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -19,6 +20,8 @@ internal class GroupJoinExpression : IEnumerableE public Func, TResult> ResultSelectorCompiled { get; set; } public IEqualityComparer Comparer { get; set; } + public Expression OptSelectorExpression => ResultSelector; + public GroupJoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression, TResult>> resultSelector, Func, TResult> resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); @@ -36,6 +39,8 @@ public GroupJoinExpression(IEnumerableExpression outer, IEnumerable AsNotifiable() @@ -57,5 +62,33 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return this.Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression, TOptimizedResult>>; + return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); + } + + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index e2fb575e6..38a0a8296 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq.Expressions; using System.Text; using SL = System.Linq.Enumerable; @@ -7,7 +8,7 @@ namespace NMF.Expressions { - internal class JoinExpression : IEnumerableExpression + internal class JoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -19,6 +20,8 @@ internal class JoinExpression : IEnumerableExpres public Func ResultSelectorCompiled { get; set; } public IEqualityComparer Comparer { get; set; } + public Expression OptSelectorExpression => ResultSelector; + public JoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression> resultSelector, Func resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); @@ -36,6 +39,8 @@ public JoinExpression(IEnumerableExpression outer, IEnumerable i ResultSelector = resultSelector; ResultSelectorCompiled = resultSelectorCompiled ?? ExpressionCompileRewriter.Compile(resultSelector); Comparer = comparer; + + AddDgmlNode(); } public INotifyEnumerable AsNotifiable() @@ -63,5 +68,32 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); + } + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs new file mode 100644 index 000000000..44a710b23 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace NMF.Expressions +{ + public sealed class QueryOptimizer + { + private readonly LambdaExpression _firstLambdaSelectorExpression; + private readonly LambdaExpression _secondLambdaSelectorExpression; + + private readonly QueryOptimizerVisitor _queryOptimizerVisitor; + + //Needed for V3 + private readonly ParameterExpression _optimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); + private ObservingFunc _intermediateSelectorExpression; + + /// + /// + /// + /// + /// insert into firstSelectorExpression + public QueryOptimizer(Expression firstSelectorExpression, Expression secondSelectorExpression) + { + _firstLambdaSelectorExpression = firstSelectorExpression as LambdaExpression; + _secondLambdaSelectorExpression = secondSelectorExpression as LambdaExpression; + _queryOptimizerVisitor = new QueryOptimizerVisitor(_firstLambdaSelectorExpression, _secondLambdaSelectorExpression); + } + + public Expression Optimize() + { + return MergeLambdaExpressions(); + //return MergeLambdaExpressionsWithVariables(); + } + + + public Expression MergeLambdaExpressions() + { + var builtExpression = _queryOptimizerVisitor.Visit(_firstLambdaSelectorExpression) as LambdaExpression; + return Expression.Lambda(builtExpression.Body, _secondLambdaSelectorExpression.Parameters); + } + + public Expression MergeLambdaExpressionsWithVariables() + { + _queryOptimizerVisitor.OptimizationVaribable = _optimizationVaribable; + //TODO: Methode schwer verständlich. Kann man kleinere Untermethoden erstellen die beschreibenden Namen haben? + + var p = Expression.Lambda(_firstLambdaSelectorExpression.Body, _secondLambdaSelectorExpression.Parameters[0], _optimizationVaribable); + var builtLambdaExpression = _queryOptimizerVisitor.Visit(p); + + this._intermediateSelectorExpression = new ObservingFunc(builtLambdaExpression as Expression>); + + var methodInfo = typeof(ObservingFunc).GetMethod("Evaluate", new[] { typeof(TSource), typeof(TResult) }); + var constantExpr = Expression.Constant(_intermediateSelectorExpression); + + var newLamdaExpression = Expression.Lambda( + Expression.Call(constantExpr, methodInfo, this._secondLambdaSelectorExpression.Parameters[0], _secondLambdaSelectorExpression.Body), + this._secondLambdaSelectorExpression.Parameters + ); + + return newLamdaExpression; + } + + + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs new file mode 100644 index 000000000..9e5ca02e0 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs @@ -0,0 +1,35 @@ +using System.Linq.Expressions; +using System.Runtime.CompilerServices; + +namespace NMF.Expressions +{ + public class QueryOptimizerVisitor: ExpressionVisitorBase + { + private readonly LambdaExpression _firstLambdaSelectorExpression; + private readonly LambdaExpression _secondLambdaSelectorExpression; + + public ParameterExpression OptimizationVaribable { get; set; } + + public QueryOptimizerVisitor(LambdaExpression firstLambdaSelectorExpression, LambdaExpression secondLambdaSelectorExpression) + { + _firstLambdaSelectorExpression = firstLambdaSelectorExpression; + _secondLambdaSelectorExpression = secondLambdaSelectorExpression; + } + + protected override Expression VisitParameter(ParameterExpression node) + { + var param = _firstLambdaSelectorExpression.Parameters[0]; + + if (node.ToString().Equals(param.ToString())) + { + if(OptimizationVaribable != null) + return base.VisitParameter(OptimizationVaribable); + + //anstelle des Parameters, die zweite LambdaExpression einfügen + return _secondLambdaSelectorExpression.Body; + } + return base.VisitParameter(node); + } + + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 341dbe27b..b22466056 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; @@ -8,11 +9,12 @@ namespace NMF.Expressions { - internal class SelectExpression : IEnumerableExpression + internal class SelectExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression> SelectorExpression { get; private set; } public Func SelectorCompiled { get; private set; } + public Expression OptSelectorExpression => SelectorExpression; public SelectExpression(IEnumerableExpression source, Expression> selector, Func selectorCompiled) { @@ -23,10 +25,18 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() { + //TODO: Wie oben erst eine IsOptimizable Methode aufrufen und falls true Optimize aufrufen. Dadurch spart man sich hier wieder den != this Vergleich + IEnumerableExpression optimizedExpression = AsOptimized(); + + if (optimizedExpression != this) + return optimizedExpression.AsNotifiable(); + return Source.AsNotifiable().Select(SelectorExpression); } @@ -44,5 +54,59 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + + VisitForDebugging(SelectorExpression); + + //TODO: Aufruf hier weglassen + IEnumerableExpression optimizedExpression = this.Optimize(Source); + + //Wenn expression == null : Ausgangspunkt der Optimierung + if (expression != null) + { + //TODO: Hier eine IsOptimizable() Methode in einem if aufrufen (prüft nur den Typ) + + //TODO: Dadurch kann man sich die Überprüfung mit != this sparen + //if return value of optimize() is the caller of this method + //nothing can be optimized + if (optimizedExpression != this) + { + + //TODO: Dann hier erst Optimize Extension Method Aufrufen und den Rückgabetyp ändern um anschließenden Cast zu sparen + //TODO: bzw. wieso muss man hier nochmal AsOptimized aufrufen? Wurde doch oben in der Optimize ExtMethod gemacht wenn Typ passt! + + //test != this: eine bereit neu erstellte Expression soll weiter optimiert werden + var castedOptimizedExpression = optimizedExpression as IOptimizableEnumerableExpression; + return castedOptimizedExpression.AsOptimized(expression); + } + + //Create new Expression + return Merge(expression); + } + + return (IEnumerableExpression)optimizedExpression; + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new SelectExpression(Source, mergedSelectorExpression, null); + } + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index a0ab72ff8..9007f9060 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; @@ -8,7 +9,7 @@ namespace NMF.Expressions { - internal class SelectManyExpression : IEnumerableExpression + internal class SelectManyExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression>> FuncExpression { get; private set; } @@ -16,6 +17,8 @@ internal class SelectManyExpression : IEnumerab public Expression> ResultSelector { get; private set; } public Func ResultSelectorCompiled { get; private set; } + public Expression OptSelectorExpression => ResultSelector; + public SelectManyExpression(IEnumerableExpression source, Expression>> func, Func> funcCompiled, Expression> resultSelector, Func resultSelectorCompiled) { if (source == null) throw new ArgumentNullException("source"); @@ -27,6 +30,8 @@ public SelectManyExpression(IEnumerableExpression source, Expression AsNotifiable() @@ -48,5 +53,33 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return this.Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); + } + + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/Expressions.Linq.csproj b/Expressions/Expressions.Linq/Expressions.Linq.csproj index 90afdb7f5..f01abe3d1 100644 --- a/Expressions/Expressions.Linq/Expressions.Linq.csproj +++ b/Expressions/Expressions.Linq/Expressions.Linq.csproj @@ -38,6 +38,8 @@ + + @@ -45,13 +47,18 @@ + + + + + @@ -62,6 +69,7 @@ + @@ -101,6 +109,10 @@ + + {868226d4-bc8b-4b91-bd09-8f63d3c9debe} + Utilities + {afca9d1d-26a6-482a-a5ab-0827ad0fd677} Expressions diff --git a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs index c6130ad1c..cdd18adac 100644 --- a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs +++ b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs @@ -2,10 +2,29 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Text; namespace NMF.Expressions { + /// + /// Represents a collection that can be optimized + /// + internal interface IOptimizableEnumerableExpression + { + Expression OptSelectorExpression { get; } + + /// + /// Gets optimization for this collection + /// + /// + /// + /// + IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null); + + IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr); + } + /// /// Represents a collection that can be accessed incrementally, i.e. with change notifications /// diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs new file mode 100644 index 000000000..55caca44e --- /dev/null +++ b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace NMF.Expressions.Linq +{ + /// + /// Defines a set of extension methods + /// + internal static class OptimizableEnumerableExpressionExtensions + { + internal static IEnumerableExpression Optimize(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) + { + if (source is IOptimizableEnumerableExpression) + { + var castedSource = source as IOptimizableEnumerableExpression; + return castedSource.AsOptimized(optimizableEnumerableExpression); ; + } + return (IEnumerableExpression)optimizableEnumerableExpression; + } + } +} \ No newline at end of file diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index a13004561..be5ca9d7f 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -462,6 +462,159 @@ from te2 in te1.ConnectsTo Assert.AreEqual(func.Count(), incremental.Count()); } + private IEnumerableExpression CreateSelectManySelectManyExpressionOptimizable() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + from sensor in route.DefinedBy + select swP.Position.ToString() + sensor.Id.ToString()); + //select swP.Position.ToString()); + + //DmglVisualizer.OpenDgml(); + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + + //DmglVisualizer.OpenDgml(); + + + return func; + } + + private IEnumerableExpression CreateJoinSelectExpressionOptimizable() + { + DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + let routeString = route.ToString() + select swP.Position.ToString()); + //select swP.Position.ToString()); + + DmglVisualizer.OpenDgml(); + + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + return func; + } + + [TestMethod] + public void NotifySystem_Optimize_SelectSelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression(from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + //from swP in route.Follows.OfType() + //where swP.Switch.CurrentPosition != swP.Position + let routeString = route.ToString() + select route.ToIdentifierString() + routeString); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + + routeTest.Entry.Signal = Signal.STOP; + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + + [TestMethod] + public void NotifySystem_Optimize_SelectSelectSelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + let routeEntry = route.Entry.ToString() + let routeString = route.ToString() + select routeEntry + routeString); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + routeTest.Entry = new Semaphore(); + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + + [TestMethod] + public void NotifySystem_Optimize_SelectManySelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + let routeString = route.ToString() + select swP.Position.ToString()); + //select swP.Position.ToString()); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + routeTest.Entry = new Semaphore(); + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + private IEnumerableExpression CreateExpression(IEnumerableExpression value) { return value; From 22bd08510ae2feb101efda62f1650ba3b0feed40 Mon Sep 17 00:00:00 2001 From: marcu Date: Mon, 5 Mar 2018 16:57:51 +0100 Subject: [PATCH 02/10] current state for code-review --- .../EnumerableExpressions/DebugVisitor.cs | 38 ++++ .../EnumerableExpressions/DmglVisualizer.cs | 132 ++++++++++++++ .../DynamicDependencyGraphDgmlVisualizer.cs | 162 ++++++++++++++++++ .../GroupJoinExpression.cs | 35 +++- .../EnumerableExpressions/JoinExpression.cs | 34 +++- .../EnumerableExpressions/QueryOptimizer.cs | 68 ++++++++ .../QueryOptimizerVisitor.cs | 35 ++++ .../EnumerableExpressions/SelectExpression.cs | 66 ++++++- .../SelectManyExpression.cs | 35 +++- .../Expressions.Linq/Expressions.Linq.csproj | 2 + .../Facade/IEnumerableExpression.cs | 19 ++ .../Facade/OptimizableExpressionExtensions.cs | 23 +++ .../Expressions.Linq.Net45.csproj | 24 +++ .../NotifySystemTests.cs | 153 +++++++++++++++++ 14 files changed, 822 insertions(+), 4 deletions(-) create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs create mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs create mode 100644 Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs new file mode 100644 index 000000000..8c8c49658 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DebugVisitor.cs @@ -0,0 +1,38 @@ +using System.Linq.Expressions; + +namespace NMF.Expressions +{ + public class DebugVisitor : ExpressionVisitor + { + private int level = 0; + + public override Expression Visit(Expression exp) + { + if (exp != null) + { + if (level == 0) + { + System.Diagnostics.Debug.WriteLine("#################################"); + } + + + for (int i = 0; i < level; i++) + { + System.Diagnostics.Debug.Write("   "); + } + System.Diagnostics.Debug.WriteLine("{0}  -  {1} : || {2} ||", + exp.NodeType, exp.GetType().Name, exp.ToString()); + } + level++; + Expression result = base.Visit(exp); + level--; + return result; + } + + public void Display(Expression exp) + { + System.Diagnostics.Debug.WriteLine("===== DisplayVisitor.Display ====="); + this.Visit(exp); + } + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs new file mode 100644 index 000000000..86d073739 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Security.Cryptography.X509Certificates; +using System.Xml.Linq; + +namespace NMF.Expressions +{ + public static class DmglVisualizer + { + public static XDocument Doc { get; set; } + + private static XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml"); + + private static int lastAddedNodeId; + + public static void Initialize() + { + Doc = CreateDgmlDoc(); + var nodes = Doc.Root.Element(ns + "Nodes"); + var links = Doc.Root.Element(ns + "Links"); + + lastAddedNodeId = 0; + } + + public static void AddNode(IEnumerableExpression node) + { + if(Doc == null) return; + var nodes = Doc.Root.Element(ns + "Nodes"); + var nodeToAdd = ToDgmlNode(node); + nodes.Add(nodeToAdd); + } + + private static XElement ToDgmlLink(IEnumerableExpression node) + { + var e = new XElement(ns + "Link"); + e.SetAttributeValue("Source", node.GetHashCode()); + e.SetAttributeValue("Target", lastAddedNodeId); + return e; + } + + private static XElement ToDgmlNode(IEnumerableExpression node) + { + var links = Doc.Root.Element(ns + "Links"); + + var e = new XElement(ns + "Node"); + + if (lastAddedNodeId != 0) + links.Add(ToDgmlLink(node)); + + lastAddedNodeId = node.GetHashCode(); + e.SetAttributeValue("Id", lastAddedNodeId); + e.SetAttributeValue("Label", NodeToLabel(node)); + + return e; + + } + + public static void OpenDgml() + { + OpenDgml(Doc); + } + + + private static XDocument CreateDgmlDoc() + { + var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + doc.Add(new XElement(ns + "DirectedGraph")); + doc.Root.SetAttributeValue("Layout", "Sugiyama"); + doc.Root.SetAttributeValue("GraphDirection", "BottomToTop"); + var nodes = new XElement(ns + "Nodes"); + doc.Root.Add(nodes); + var links = new XElement(ns + "Links"); + doc.Root.Add(links); + var categories = new XElement(ns + "Categories"); + doc.Root.Add(categories); + var potentialChangeSource = new XElement(ns + "Category"); + potentialChangeSource.SetAttributeValue("Id", "PotentialChangeSource"); + potentialChangeSource.SetAttributeValue("Background", "LightBlue"); + categories.Add(potentialChangeSource); + var actualChangeSource = new XElement(ns + "Category"); + actualChangeSource.SetAttributeValue("Id", "ActualChangeSource"); + actualChangeSource.SetAttributeValue("Background", "Green"); + actualChangeSource.SetAttributeValue("Stroke", "Green"); + actualChangeSource.SetAttributeValue("StrokeThickness", "3"); + categories.Add(actualChangeSource); + var syncNode = new XElement(ns + "Category"); + syncNode.SetAttributeValue("Id", "SyncNode"); + syncNode.SetAttributeValue("Background", "Red"); + categories.Add(syncNode); + return doc; + } + + private static void OpenDgml(XDocument doc) + { + var fileName = DateTime.Now.ToString("hh-mm-ss-ff") + ".dgml"; + var filePath = Path.Combine(Path.GetTempPath(), fileName); + doc.Save(filePath); + System.Diagnostics.Process.Start(filePath); + } + + + + private static string NodeToLabel(IEnumerableExpression node) + { + var typeName = node.GetType().Name; + var result = typeName.Replace("Observable", ""); + int genericIndex = result.IndexOf('`'); + if (genericIndex > 0) + result = result.Remove(genericIndex); + + var valueProp = node.GetType().GetProperties().FirstOrDefault(p => p.Name == "Value"); + if (valueProp != null) + result += "\nValue: " + valueProp.GetValue(node); + + var countProp = node.GetType().GetProperty("Count"); + if (countProp != null) + result += "\nCount: " + countProp.GetValue(node); + + return result; + } + + + + + } + + +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs new file mode 100644 index 000000000..9481298b4 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs @@ -0,0 +1,162 @@ +using NMF.Expressions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +//using TrainBenchmark; + +namespace NMF.Expressions.EnumerableExpressions +{ + public static class DDGDgmlVisualizer + { + private static XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml"); + + public static void initDgmlVisualizer(INotifyEnumerable func) + { + //var test = new SwitchSet(); + //var query = test.Data.Query; + var changeSources = Enumerable.Empty(); + + var doc = CreateDgml(func, changeSources); + OpenDgml(doc); + } + + private static XDocument CreateDgml(INotifiable query, IEnumerable changeSources) + { + var doc = CreateDgmlDoc(); + var nodes = doc.Root.Element(ns + "Nodes"); + var links = doc.Root.Element(ns + "Links"); + + var allNodes = new[] { query }.Concat(NMF.Utilities.Extensions.SelectRecursive(query, n => n.Dependencies)).ToList(); + foreach (var node in allNodes) + { + nodes.Add(ToDgmlNode(node)); + foreach (var link in ToDgmlLink(node)) + links.Add(link); + } + + var sourceNodesIds = changeSources.Select(n => n.GetHashCode().ToString()).ToList(); + var actualSources = nodes.Elements().Where(e => sourceNodesIds.Contains(e.Attribute("Id").Value)); + foreach (var s in actualSources) + s.SetAttributeValue("Category", "ActualChangeSource"); + + var syncNodes = FindSyncNodes(changeSources); + var syncNodesIds = syncNodes.Select(n => n.GetHashCode().ToString()).ToList(); + var syncs = nodes.Elements().Where(e => syncNodesIds.Contains(e.Attribute("Id").Value)); + foreach (var s in syncs) + s.SetAttributeValue("Category", "SyncNode"); + + foreach (var node in changeSources) + { + var path = NMF.Utilities.Extensions.SelectRecursive(node, n => n.Successors).ToList(); + for (int i = 0; i < path.Count - 1; i++) + { + var src = path[i]; + var dst = path[i + 1]; + var link = links.Elements().First(e => e.Attribute("Source").Value == src.GetHashCode().ToString() && e.Attribute("Target").Value == dst.GetHashCode().ToString()); + link.SetAttributeValue("Category", "ActualChangeSource"); + } + } + + return doc; + } + + private static void OpenDgml(XDocument doc) + { + var fileName = DateTime.Now.ToString("hh-mm-ss") + ".dgml"; + var filePath = Path.Combine(Path.GetTempPath(), fileName); + doc.Save(filePath); + System.Diagnostics.Process.Start(filePath); + } + + private static XDocument CreateDgmlDoc() + { + var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); + doc.Add(new XElement(ns + "DirectedGraph")); + doc.Root.SetAttributeValue("Layout", "Sugiyama"); + doc.Root.SetAttributeValue("GraphDirection", "BottomToTop"); + var nodes = new XElement(ns + "Nodes"); + doc.Root.Add(nodes); + var links = new XElement(ns + "Links"); + doc.Root.Add(links); + var categories = new XElement(ns + "Categories"); + doc.Root.Add(categories); + var potentialChangeSource = new XElement(ns + "Category"); + potentialChangeSource.SetAttributeValue("Id", "PotentialChangeSource"); + potentialChangeSource.SetAttributeValue("Background", "LightBlue"); + categories.Add(potentialChangeSource); + var actualChangeSource = new XElement(ns + "Category"); + actualChangeSource.SetAttributeValue("Id", "ActualChangeSource"); + actualChangeSource.SetAttributeValue("Background", "Green"); + actualChangeSource.SetAttributeValue("Stroke", "Green"); + actualChangeSource.SetAttributeValue("StrokeThickness", "3"); + categories.Add(actualChangeSource); + var syncNode = new XElement(ns + "Category"); + syncNode.SetAttributeValue("Id", "SyncNode"); + syncNode.SetAttributeValue("Background", "Red"); + categories.Add(syncNode); + return doc; + } + + private static XElement ToDgmlNode(INotifiable node) + { + var e = new XElement(ns + "Node"); + e.SetAttributeValue("Id", node.GetHashCode()); + e.SetAttributeValue("Label", NodeToLabel(node)); + return e; + } + + private static string NodeToLabel(INotifiable node) + { + var typeName = node.GetType().Name; + var result = typeName.Replace("Observable", ""); + int genericIndex = result.IndexOf('`'); + if (genericIndex > 0) + result = result.Remove(genericIndex); + + var valueProp = node.GetType().GetProperties().FirstOrDefault(p => p.Name == "Value"); + if (valueProp != null) + result += "\nValue: " + valueProp.GetValue(node); + + var countProp = node.GetType().GetProperty("Count"); + if (countProp != null) + result += "\nCount: " + countProp.GetValue(node); + + return result; + } + + private static IEnumerable ToDgmlLink(INotifiable node) + { + return node.Dependencies.Select(d => + { + var e = new XElement(ns + "Link"); + e.SetAttributeValue("Source", d.GetHashCode()); + e.SetAttributeValue("Target", node.GetHashCode()); + return e; + }); + } + + private static List FindSyncNodes(IEnumerable sourceNodes) + { + var result = new List(); + var visited = new HashSet(); + var stack = new Stack(sourceNodes); + + while (stack.Any()) + { + var item = stack.Pop(); + visited.Add(item.GetHashCode()); + foreach (var suc in item.Successors) + stack.Push(suc); + + if (item.Dependencies.Count(d => visited.Contains(d.GetHashCode())) == 2) + result.Add(item); + } + + return result; + } + } +} diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index e9f8ba538..65fa3bfcd 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq.Expressions; using System.Text; using SL = System.Linq.Enumerable; @@ -7,7 +8,7 @@ namespace NMF.Expressions { - internal class GroupJoinExpression : IEnumerableExpression + internal class GroupJoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -20,6 +21,8 @@ internal class GroupJoinExpression : IEnumerableE public IEqualityComparer Comparer { get; set; } private INotifyEnumerable notifyEnumerable; + public Expression OptSelectorExpression => ResultSelector; + public GroupJoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression, TResult>> resultSelector, Func, TResult> resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); @@ -37,6 +40,8 @@ public GroupJoinExpression(IEnumerableExpression outer, IEnumerable AsNotifiable() @@ -63,5 +68,33 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return this.Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression, TOptimizedResult>>; + return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); + } + + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index da09ee1d0..4d9d36446 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq.Expressions; using System.Text; using SL = System.Linq.Enumerable; @@ -7,7 +8,7 @@ namespace NMF.Expressions { - internal class JoinExpression : IEnumerableExpression + internal class JoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -20,6 +21,8 @@ internal class JoinExpression : IEnumerableExpres public IEqualityComparer Comparer { get; set; } private INotifyEnumerable notifyEnumerable; + public Expression OptSelectorExpression => ResultSelector; + public JoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression> resultSelector, Func resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); @@ -37,6 +40,8 @@ public JoinExpression(IEnumerableExpression outer, IEnumerable i ResultSelector = resultSelector; ResultSelectorCompiled = resultSelectorCompiled ?? ExpressionCompileRewriter.Compile(resultSelector); Comparer = comparer; + + AddDgmlNode(); } public INotifyEnumerable AsNotifiable() @@ -69,5 +74,32 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); + } + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs new file mode 100644 index 000000000..44a710b23 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace NMF.Expressions +{ + public sealed class QueryOptimizer + { + private readonly LambdaExpression _firstLambdaSelectorExpression; + private readonly LambdaExpression _secondLambdaSelectorExpression; + + private readonly QueryOptimizerVisitor _queryOptimizerVisitor; + + //Needed for V3 + private readonly ParameterExpression _optimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); + private ObservingFunc _intermediateSelectorExpression; + + /// + /// + /// + /// + /// insert into firstSelectorExpression + public QueryOptimizer(Expression firstSelectorExpression, Expression secondSelectorExpression) + { + _firstLambdaSelectorExpression = firstSelectorExpression as LambdaExpression; + _secondLambdaSelectorExpression = secondSelectorExpression as LambdaExpression; + _queryOptimizerVisitor = new QueryOptimizerVisitor(_firstLambdaSelectorExpression, _secondLambdaSelectorExpression); + } + + public Expression Optimize() + { + return MergeLambdaExpressions(); + //return MergeLambdaExpressionsWithVariables(); + } + + + public Expression MergeLambdaExpressions() + { + var builtExpression = _queryOptimizerVisitor.Visit(_firstLambdaSelectorExpression) as LambdaExpression; + return Expression.Lambda(builtExpression.Body, _secondLambdaSelectorExpression.Parameters); + } + + public Expression MergeLambdaExpressionsWithVariables() + { + _queryOptimizerVisitor.OptimizationVaribable = _optimizationVaribable; + //TODO: Methode schwer verständlich. Kann man kleinere Untermethoden erstellen die beschreibenden Namen haben? + + var p = Expression.Lambda(_firstLambdaSelectorExpression.Body, _secondLambdaSelectorExpression.Parameters[0], _optimizationVaribable); + var builtLambdaExpression = _queryOptimizerVisitor.Visit(p); + + this._intermediateSelectorExpression = new ObservingFunc(builtLambdaExpression as Expression>); + + var methodInfo = typeof(ObservingFunc).GetMethod("Evaluate", new[] { typeof(TSource), typeof(TResult) }); + var constantExpr = Expression.Constant(_intermediateSelectorExpression); + + var newLamdaExpression = Expression.Lambda( + Expression.Call(constantExpr, methodInfo, this._secondLambdaSelectorExpression.Parameters[0], _secondLambdaSelectorExpression.Body), + this._secondLambdaSelectorExpression.Parameters + ); + + return newLamdaExpression; + } + + + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs new file mode 100644 index 000000000..9e5ca02e0 --- /dev/null +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs @@ -0,0 +1,35 @@ +using System.Linq.Expressions; +using System.Runtime.CompilerServices; + +namespace NMF.Expressions +{ + public class QueryOptimizerVisitor: ExpressionVisitorBase + { + private readonly LambdaExpression _firstLambdaSelectorExpression; + private readonly LambdaExpression _secondLambdaSelectorExpression; + + public ParameterExpression OptimizationVaribable { get; set; } + + public QueryOptimizerVisitor(LambdaExpression firstLambdaSelectorExpression, LambdaExpression secondLambdaSelectorExpression) + { + _firstLambdaSelectorExpression = firstLambdaSelectorExpression; + _secondLambdaSelectorExpression = secondLambdaSelectorExpression; + } + + protected override Expression VisitParameter(ParameterExpression node) + { + var param = _firstLambdaSelectorExpression.Parameters[0]; + + if (node.ToString().Equals(param.ToString())) + { + if(OptimizationVaribable != null) + return base.VisitParameter(OptimizationVaribable); + + //anstelle des Parameters, die zweite LambdaExpression einfügen + return _secondLambdaSelectorExpression.Body; + } + return base.VisitParameter(node); + } + + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 939cc3809..90c60996c 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; @@ -8,12 +9,13 @@ namespace NMF.Expressions { - internal class SelectExpression : IEnumerableExpression + internal class SelectExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression> SelectorExpression { get; private set; } public Func SelectorCompiled { get; private set; } private INotifyEnumerable notifyEnumerable; + public Expression OptSelectorExpression => SelectorExpression; public SelectExpression(IEnumerableExpression source, Expression> selector, Func selectorCompiled) { @@ -24,6 +26,8 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() @@ -33,6 +37,12 @@ public INotifyEnumerable AsNotifiable() notifyEnumerable = Source.AsNotifiable().Select(SelectorExpression); } return notifyEnumerable; + //TODO: Wie oben erst eine IsOptimizable Methode aufrufen und falls true Optimize aufrufen. Dadurch spart man sich hier wieder den != this Vergleich + IEnumerableExpression optimizedExpression = AsOptimized(); + + if (optimizedExpression != this) + return optimizedExpression.AsNotifiable(); + } public IEnumerator GetEnumerator() @@ -50,5 +60,59 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + + VisitForDebugging(SelectorExpression); + + //TODO: Aufruf hier weglassen + IEnumerableExpression optimizedExpression = this.Optimize(Source); + + //Wenn expression == null : Ausgangspunkt der Optimierung + if (expression != null) + { + //TODO: Hier eine IsOptimizable() Methode in einem if aufrufen (prüft nur den Typ) + + //TODO: Dadurch kann man sich die Überprüfung mit != this sparen + //if return value of optimize() is the caller of this method + //nothing can be optimized + if (optimizedExpression != this) + { + + //TODO: Dann hier erst Optimize Extension Method Aufrufen und den Rückgabetyp ändern um anschließenden Cast zu sparen + //TODO: bzw. wieso muss man hier nochmal AsOptimized aufrufen? Wurde doch oben in der Optimize ExtMethod gemacht wenn Typ passt! + + //test != this: eine bereit neu erstellte Expression soll weiter optimiert werden + var castedOptimizedExpression = optimizedExpression as IOptimizableEnumerableExpression; + return castedOptimizedExpression.AsOptimized(expression); + } + + //Create new Expression + return Merge(expression); + } + + return (IEnumerableExpression)optimizedExpression; + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new SelectExpression(Source, mergedSelectorExpression, null); + } + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index e83622eed..0d7dc5d66 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Text; @@ -8,7 +9,7 @@ namespace NMF.Expressions { - internal class SelectManyExpression : IEnumerableExpression + internal class SelectManyExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression>> FuncExpression { get; private set; } @@ -17,6 +18,8 @@ internal class SelectManyExpression : IEnumerab public Func ResultSelectorCompiled { get; private set; } private INotifyEnumerable notifyEnumerable; + public Expression OptSelectorExpression => ResultSelector; + public SelectManyExpression(IEnumerableExpression source, Expression>> func, Func> funcCompiled, Expression> resultSelector, Func resultSelectorCompiled) { if (source == null) throw new ArgumentNullException("source"); @@ -28,6 +31,8 @@ public SelectManyExpression(IEnumerableExpression source, Expression AsNotifiable() @@ -54,5 +59,33 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); } + + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + { + VisitForDebugging(ResultSelector); + + return this.Merge(expression); + } + + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + { + var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); + } + + + [Conditional("DEBUG")] + public void AddDgmlNode() + { + DmglVisualizer.AddNode(this); + } + + [Conditional("DEBUG")] + private void VisitForDebugging(dynamic expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } } } diff --git a/Expressions/Expressions.Linq/Expressions.Linq.csproj b/Expressions/Expressions.Linq/Expressions.Linq.csproj index 5c083b5d7..0bf73dd8d 100644 --- a/Expressions/Expressions.Linq/Expressions.Linq.csproj +++ b/Expressions/Expressions.Linq/Expressions.Linq.csproj @@ -9,10 +9,12 @@ + + diff --git a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs index c6130ad1c..cdd18adac 100644 --- a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs +++ b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs @@ -2,10 +2,29 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Text; namespace NMF.Expressions { + /// + /// Represents a collection that can be optimized + /// + internal interface IOptimizableEnumerableExpression + { + Expression OptSelectorExpression { get; } + + /// + /// Gets optimization for this collection + /// + /// + /// + /// + IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null); + + IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr); + } + /// /// Represents a collection that can be accessed incrementally, i.e. with change notifications /// diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs new file mode 100644 index 000000000..55caca44e --- /dev/null +++ b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +namespace NMF.Expressions.Linq +{ + /// + /// Defines a set of extension methods + /// + internal static class OptimizableEnumerableExpressionExtensions + { + internal static IEnumerableExpression Optimize(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) + { + if (source is IOptimizableEnumerableExpression) + { + var castedSource = source as IOptimizableEnumerableExpression; + return castedSource.AsOptimized(optimizableEnumerableExpression); ; + } + return (IEnumerableExpression)optimizableEnumerableExpression; + } + } +} \ No newline at end of file diff --git a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj index ac9475dae..d3ad9b68c 100644 --- a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj +++ b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj @@ -33,6 +33,8 @@ + + @@ -44,9 +46,18 @@ EnumerableExpressions\ConcatExpression.cs + + EnumerableExpressions\DebugVisitor.cs + EnumerableExpressions\DistinctExpression.cs + + EnumerableExpressions\DmglVisualizer.cs + + + EnumerableExpressions\DynamicDependencyGraphDgmlVisualizer.cs + EnumerableExpressions\ExceptExpression.cs @@ -65,6 +76,12 @@ EnumerableExpressions\OrderByExpression.cs + + EnumerableExpressions\QueryOptimizer.cs + + + EnumerableExpressions\QueryOptimizerVisitor.cs + EnumerableExpressions\SelectExpression.cs @@ -95,6 +112,9 @@ Facade\ObservableExtensions.cs + + Facade\OptimizableExpressionExtensions.cs + Facade\OrderableList.cs @@ -209,6 +229,10 @@ + + {5f426e12-0fe2-4240-967c-1cfbc0fc30cf} + Utilities.Net45 + {ca44f2b7-551e-43b2-8c95-00102feed9a7} Expressions.Net45 diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index a13004561..be5ca9d7f 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -462,6 +462,159 @@ from te2 in te1.ConnectsTo Assert.AreEqual(func.Count(), incremental.Count()); } + private IEnumerableExpression CreateSelectManySelectManyExpressionOptimizable() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + from sensor in route.DefinedBy + select swP.Position.ToString() + sensor.Id.ToString()); + //select swP.Position.ToString()); + + //DmglVisualizer.OpenDgml(); + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + + //DmglVisualizer.OpenDgml(); + + + return func; + } + + private IEnumerableExpression CreateJoinSelectExpressionOptimizable() + { + DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + let routeString = route.ToString() + select swP.Position.ToString()); + //select swP.Position.ToString()); + + DmglVisualizer.OpenDgml(); + + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + return func; + } + + [TestMethod] + public void NotifySystem_Optimize_SelectSelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression(from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + //from swP in route.Follows.OfType() + //where swP.Switch.CurrentPosition != swP.Position + let routeString = route.ToString() + select route.ToIdentifierString() + routeString); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + + routeTest.Entry.Signal = Signal.STOP; + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + + [TestMethod] + public void NotifySystem_Optimize_SelectSelectSelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + let routeEntry = route.Entry.ToString() + let routeString = route.ToString() + select routeEntry + routeString); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + routeTest.Entry = new Semaphore(); + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + + [TestMethod] + public void NotifySystem_Optimize_SelectManySelect() + { + //DmglVisualizer.Initialize(); + + var func = CreateExpression( + from route in RailwayContainer.Routes + where route.Entry != null && route.Entry.Signal == Signal.GO + from swP in route.Follows.OfType() + let routeString = route.ToString() + select swP.Position.ToString()); + //select swP.Position.ToString()); + + //DmglVisualizer.OpenDgml(); + + var routeTest = RailwayContainer.Routes[0]; + + var test = func.AsNotifiable(); + + //DDGDgmlVisualizer.initDgmlVisualizer(test); + + var resultChanged = false; + test.CollectionChanged += (o, e) => + { + resultChanged = true; + }; + + Assert.AreEqual(func.Count(), test.Count()); + Assert.IsFalse(resultChanged); + + routeTest.Entry = new Semaphore(); + + Assert.IsTrue(resultChanged); + Assert.AreEqual(func.Count(), test.Count()); + } + private IEnumerableExpression CreateExpression(IEnumerableExpression value) { return value; From 292786d670126ffd88f05d3a8cc84999c513965b Mon Sep 17 00:00:00 2001 From: marcu Date: Wed, 7 Mar 2018 13:43:34 +0100 Subject: [PATCH 03/10] merge faults --- .../EnumerableExpressions/GroupJoinExpression.cs | 2 -- .../EnumerableExpressions/JoinExpression.cs | 2 -- .../EnumerableExpressions/SelectExpression.cs | 11 ++++++----- .../EnumerableExpressions/SelectManyExpression.cs | 2 -- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index b21dba31c..65fa3bfcd 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -23,8 +23,6 @@ internal class GroupJoinExpression : IEnumerableE public Expression OptSelectorExpression => ResultSelector; - public Expression OptSelectorExpression => ResultSelector; - public GroupJoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression, TResult>> resultSelector, Func, TResult> resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index af154e323..4d9d36446 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -23,8 +23,6 @@ internal class JoinExpression : IEnumerableExpres public Expression OptSelectorExpression => ResultSelector; - public Expression OptSelectorExpression => ResultSelector; - public JoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression> resultSelector, Func resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 90c60996c..e61e73c49 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -14,6 +14,7 @@ internal class SelectExpression : IEnumerableExpression Source { get; private set; } public Expression> SelectorExpression { get; private set; } public Func SelectorCompiled { get; private set; } + private INotifyEnumerable notifyEnumerable; public Expression OptSelectorExpression => SelectorExpression; @@ -32,17 +33,17 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() { - if (notifyEnumerable == null) - { - notifyEnumerable = Source.AsNotifiable().Select(SelectorExpression); - } - return notifyEnumerable; //TODO: Wie oben erst eine IsOptimizable Methode aufrufen und falls true Optimize aufrufen. Dadurch spart man sich hier wieder den != this Vergleich IEnumerableExpression optimizedExpression = AsOptimized(); if (optimizedExpression != this) return optimizedExpression.AsNotifiable(); + if (notifyEnumerable == null) + { + notifyEnumerable = Source.AsNotifiable().Select(SelectorExpression); + } + return notifyEnumerable; } public IEnumerator GetEnumerator() diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index fff2daf51..0d7dc5d66 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -20,8 +20,6 @@ internal class SelectManyExpression : IEnumerab public Expression OptSelectorExpression => ResultSelector; - public Expression OptSelectorExpression => ResultSelector; - public SelectManyExpression(IEnumerableExpression source, Expression>> func, Func> funcCompiled, Expression> resultSelector, Func resultSelectorCompiled) { if (source == null) throw new ArgumentNullException("source"); From 9a317c84883de703d28e24a13914494bf0ed3896 Mon Sep 17 00:00:00 2001 From: marcu Date: Wed, 7 Mar 2018 15:23:35 +0100 Subject: [PATCH 04/10] queryOptimizer is no longer generic; type parameters are now passed via method; comments for queryOptimizer; --- .../GroupJoinExpression.cs | 10 +- .../EnumerableExpressions/JoinExpression.cs | 9 +- .../EnumerableExpressions/QueryOptimizer.cs | 98 +++++++++++-------- .../EnumerableExpressions/SelectExpression.cs | 10 +- .../SelectManyExpression.cs | 10 +- 5 files changed, 75 insertions(+), 62 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index 65fa3bfcd..a06021af9 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -40,8 +40,9 @@ public GroupJoinExpression(IEnumerableExpression outer, IEnumerable AsNotifiable() @@ -71,25 +72,24 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) { +#if DEBUG VisitForDebugging(ResultSelector); +#endif return this.Merge(expression); } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression, TOptimizedResult>>; + var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression, TOptimizedResult>>; return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - - [Conditional("DEBUG")] public void AddDgmlNode() { DmglVisualizer.AddNode(this); } - [Conditional("DEBUG")] private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index 4d9d36446..1501e5bb9 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -40,8 +40,9 @@ public JoinExpression(IEnumerableExpression outer, IEnumerable i ResultSelector = resultSelector; ResultSelectorCompiled = resultSelectorCompiled ?? ExpressionCompileRewriter.Compile(resultSelector); Comparer = comparer; - +#if DEBUG AddDgmlNode(); +#endif } public INotifyEnumerable AsNotifiable() @@ -77,24 +78,24 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) { +#if DEBUG VisitForDebugging(ResultSelector); +#endif return Merge(expression); } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - [Conditional("DEBUG")] public void AddDgmlNode() { DmglVisualizer.AddNode(this); } - [Conditional("DEBUG")] private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs index 44a710b23..393a2f331 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs @@ -6,63 +6,75 @@ namespace NMF.Expressions { - public sealed class QueryOptimizer + /// + /// Implements query optimization approaches + /// + public static class QueryOptimizer { - private readonly LambdaExpression _firstLambdaSelectorExpression; - private readonly LambdaExpression _secondLambdaSelectorExpression; - - private readonly QueryOptimizerVisitor _queryOptimizerVisitor; - - //Needed for V3 - private readonly ParameterExpression _optimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); - private ObservingFunc _intermediateSelectorExpression; - /// - /// + /// Optimization of two consecutive expressions into one /// - /// - /// insert into firstSelectorExpression - public QueryOptimizer(Expression firstSelectorExpression, Expression secondSelectorExpression) - { - _firstLambdaSelectorExpression = firstSelectorExpression as LambdaExpression; - _secondLambdaSelectorExpression = secondSelectorExpression as LambdaExpression; - _queryOptimizerVisitor = new QueryOptimizerVisitor(_firstLambdaSelectorExpression, _secondLambdaSelectorExpression); - } - - public Expression Optimize() + /// Source type of firstExpression and Source Type of merged expression + /// Result type of firstExpression + /// Result type of secondExpression and Result Type of merged expression + /// In the query evaluation earlier occurring expression + /// In the query evaluation appearing expression after firstExpression + /// + public static Expression Optimize(Expression firstExpression, Expression secondExpression) { - return MergeLambdaExpressions(); - //return MergeLambdaExpressionsWithVariables(); + return MergeLambdaExpressions(firstExpression as LambdaExpression, secondExpression as LambdaExpression); + //return MergeLambdaExpressionsWithVariables(firstExpression as LambdaExpression, secondExpression as LambdaExpression); } - - public Expression MergeLambdaExpressions() + /// + /// Merging two expressions by inserting secondLambdaExpression into firstLambdaExpression + /// + /// + /// + /// + public static Expression MergeLambdaExpressions(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) { - var builtExpression = _queryOptimizerVisitor.Visit(_firstLambdaSelectorExpression) as LambdaExpression; - return Expression.Lambda(builtExpression.Body, _secondLambdaSelectorExpression.Parameters); + var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression); + var builtExpression = queryOptimizerVisitor.Visit(firstLambdaExpression) as LambdaExpression; + return Expression.Lambda(builtExpression.Body, secondLambdaExpression.Parameters); } - public Expression MergeLambdaExpressionsWithVariables() + /// + /// Merging two expressions by introducing a variable that represents the second expression + /// + /// Parameter type of firstLambdaExpression and Parameter type of merged expression + /// Result type of firstLambdaExpression + /// Result type of secondLambdaExpression and Result Type of merged expression + /// + /// + /// + public static Expression MergeLambdaExpressionsWithVariables(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) { - _queryOptimizerVisitor.OptimizationVaribable = _optimizationVaribable; - //TODO: Methode schwer verständlich. Kann man kleinere Untermethoden erstellen die beschreibenden Namen haben? + var introduceOptimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); + var evaluateMethodInfo = typeof(ObservingFunc).GetMethod("Evaluate", new[] { typeof(TSource), typeof(TResult) }); - var p = Expression.Lambda(_firstLambdaSelectorExpression.Body, _secondLambdaSelectorExpression.Parameters[0], _optimizationVaribable); - var builtLambdaExpression = _queryOptimizerVisitor.Visit(p); + var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression) + { + OptimizationVaribable = introduceOptimizationVaribable + }; - this._intermediateSelectorExpression = new ObservingFunc(builtLambdaExpression as Expression>); - - var methodInfo = typeof(ObservingFunc).GetMethod("Evaluate", new[] { typeof(TSource), typeof(TResult) }); - var constantExpr = Expression.Constant(_intermediateSelectorExpression); + //TODO: Methode schwer verständlich. Kann man kleinere Untermethoden erstellen die beschreibenden Namen haben? - var newLamdaExpression = Expression.Lambda( - Expression.Call(constantExpr, methodInfo, this._secondLambdaSelectorExpression.Parameters[0], _secondLambdaSelectorExpression.Body), - this._secondLambdaSelectorExpression.Parameters - ); + //Lambda expression that contains the second expression as a parameter. After visit that expression new parameter is used + var introduceOptimizationExpr = queryOptimizerVisitor.Visit(Expression.Lambda(firstLambdaExpression.Body, secondLambdaExpression.Parameters[0], introduceOptimizationVaribable)); - return newLamdaExpression; + return Expression.Lambda( + Expression.Call( + Expression.Constant( + new ObservingFunc( + introduceOptimizationExpr as Expression>) + ), + evaluateMethodInfo, + secondLambdaExpression.Parameters[0], + secondLambdaExpression.Body + ), + secondLambdaExpression.Parameters + ); } - - } } \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index e61e73c49..571f1945c 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -27,8 +27,9 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() @@ -64,8 +65,9 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) { - +#if DEBUG VisitForDebugging(SelectorExpression); +#endif //TODO: Aufruf hier weglassen IEnumerableExpression optimizedExpression = this.Optimize(Source); @@ -98,17 +100,15 @@ public IEnumerableExpression AsOptimized(IOp public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; return new SelectExpression(Source, mergedSelectorExpression, null); } - [Conditional("DEBUG")] public void AddDgmlNode() { DmglVisualizer.AddNode(this); } - [Conditional("DEBUG")] private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index 0d7dc5d66..9e6cd42ed 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -31,8 +31,9 @@ public SelectManyExpression(IEnumerableExpression source, Expression AsNotifiable() @@ -62,25 +63,24 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) { +#if DEBUG VisitForDebugging(ResultSelector); +#endif return this.Merge(expression); } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = new QueryOptimizer(prevExpr.OptSelectorExpression, OptSelectorExpression).Optimize() as Expression>; + var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); } - - [Conditional("DEBUG")] public void AddDgmlNode() { DmglVisualizer.AddNode(this); } - [Conditional("DEBUG")] private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen From 880232de29008b60b7fd05b06d3e6cac68e92a54 Mon Sep 17 00:00:00 2001 From: marcu Date: Wed, 7 Mar 2018 15:34:31 +0100 Subject: [PATCH 05/10] rename dmglVisualizer to queryExpressionDgmlVisualizer --- .../GroupJoinExpression.cs | 7 +----- .../EnumerableExpressions/JoinExpression.cs | 7 +----- ...er.cs => QueryExpressionDgmlVisualizer.cs} | 12 +--------- .../EnumerableExpressions/SelectExpression.cs | 8 ++----- .../SelectManyExpression.cs | 7 +----- .../Expressions.Linq.Net45.csproj | 6 ++--- .../NotifySystemTests.cs | 22 +++++++++---------- 7 files changed, 20 insertions(+), 49 deletions(-) rename Expressions/Expressions.Linq/EnumerableExpressions/{DmglVisualizer.cs => QueryExpressionDgmlVisualizer.cs} (98%) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index a06021af9..616638f8a 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -41,7 +41,7 @@ public GroupJoinExpression(IEnumerableExpression outer, IEnumerable Merge(IOptimiza return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - public void AddDgmlNode() - { - DmglVisualizer.AddNode(this); - } - private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index 1501e5bb9..56dbbb21d 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -41,7 +41,7 @@ public JoinExpression(IEnumerableExpression outer, IEnumerable i ResultSelectorCompiled = resultSelectorCompiled ?? ExpressionCompileRewriter.Compile(resultSelector); Comparer = comparer; #if DEBUG - AddDgmlNode(); + QueryExpressionDgmlVisualizer.AddNode(this); #endif } @@ -91,11 +91,6 @@ public IEnumerableExpression Merge(IOptimiza return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - public void AddDgmlNode() - { - DmglVisualizer.AddNode(this); - } - private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryExpressionDgmlVisualizer.cs similarity index 98% rename from Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs rename to Expressions/Expressions.Linq/EnumerableExpressions/QueryExpressionDgmlVisualizer.cs index 86d073739..918bcb285 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/DmglVisualizer.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/QueryExpressionDgmlVisualizer.cs @@ -9,7 +9,7 @@ namespace NMF.Expressions { - public static class DmglVisualizer + public static class QueryExpressionDgmlVisualizer { public static XDocument Doc { get; set; } @@ -56,7 +56,6 @@ private static XElement ToDgmlNode(IEnumerableExpression node) e.SetAttributeValue("Label", NodeToLabel(node)); return e; - } public static void OpenDgml() @@ -64,7 +63,6 @@ public static void OpenDgml() OpenDgml(Doc); } - private static XDocument CreateDgmlDoc() { var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); @@ -102,8 +100,6 @@ private static void OpenDgml(XDocument doc) System.Diagnostics.Process.Start(filePath); } - - private static string NodeToLabel(IEnumerableExpression node) { var typeName = node.GetType().Name; @@ -122,11 +118,5 @@ private static string NodeToLabel(IEnumerableExpression node) return result; } - - - - } - - } \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 571f1945c..4197cbaeb 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -28,7 +28,8 @@ public SelectExpression(IEnumerableExpression source, Expression Merge(IOptimiza return new SelectExpression(Source, mergedSelectorExpression, null); } - public void AddDgmlNode() - { - DmglVisualizer.AddNode(this); - } - private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index 9e6cd42ed..6957e3fb4 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -32,7 +32,7 @@ public SelectManyExpression(IEnumerableExpression source, Expression Merge(IOptimiza return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); } - public void AddDgmlNode() - { - DmglVisualizer.AddNode(this); - } - private void VisitForDebugging(dynamic expression) { //Ausgabe überprüfen diff --git a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj index d3ad9b68c..fb6c5f71c 100644 --- a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj +++ b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj @@ -52,9 +52,6 @@ EnumerableExpressions\DistinctExpression.cs - - EnumerableExpressions\DmglVisualizer.cs - EnumerableExpressions\DynamicDependencyGraphDgmlVisualizer.cs @@ -76,6 +73,9 @@ EnumerableExpressions\OrderByExpression.cs + + EnumerableExpressions\QueryExpressionDgmlVisualizer.cs + EnumerableExpressions\QueryOptimizer.cs diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index be5ca9d7f..aa1e06b24 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -464,7 +464,7 @@ from te2 in te1.ConnectsTo private IEnumerableExpression CreateSelectManySelectManyExpressionOptimizable() { - //DmglVisualizer.Initialize(); + //QueryExpressionDgmlVisualizer.Initialize(); var func = CreateExpression( from route in RailwayContainer.Routes @@ -474,14 +474,14 @@ from sensor in route.DefinedBy select swP.Position.ToString() + sensor.Id.ToString()); //select swP.Position.ToString()); - //DmglVisualizer.OpenDgml(); + //QueryExpressionDgmlVisualizer.OpenDgml(); var test = func.AsNotifiable(); //DDGDgmlVisualizer.initDgmlVisualizer(test); - //DmglVisualizer.OpenDgml(); + //QueryExpressionDgmlVisualizer.OpenDgml(); return func; @@ -489,7 +489,7 @@ from sensor in route.DefinedBy private IEnumerableExpression CreateJoinSelectExpressionOptimizable() { - DmglVisualizer.Initialize(); + QueryExpressionDgmlVisualizer.Initialize(); var func = CreateExpression( from route in RailwayContainer.Routes @@ -499,7 +499,7 @@ from swP in route.Follows.OfType() select swP.Position.ToString()); //select swP.Position.ToString()); - DmglVisualizer.OpenDgml(); + QueryExpressionDgmlVisualizer.OpenDgml(); var test = func.AsNotifiable(); @@ -512,7 +512,7 @@ from swP in route.Follows.OfType() [TestMethod] public void NotifySystem_Optimize_SelectSelect() { - //DmglVisualizer.Initialize(); + //QueryExpressionDgmlVisualizer.Initialize(); var func = CreateExpression(from route in RailwayContainer.Routes where route.Entry != null && route.Entry.Signal == Signal.GO @@ -521,7 +521,7 @@ public void NotifySystem_Optimize_SelectSelect() let routeString = route.ToString() select route.ToIdentifierString() + routeString); - //DmglVisualizer.OpenDgml(); + //QueryExpressionDgmlVisualizer.OpenDgml(); var routeTest = RailwayContainer.Routes[0]; var test = func.AsNotifiable(); @@ -547,7 +547,7 @@ public void NotifySystem_Optimize_SelectSelect() [TestMethod] public void NotifySystem_Optimize_SelectSelectSelect() { - //DmglVisualizer.Initialize(); + //QueryExpressionDgmlVisualizer.Initialize(); var func = CreateExpression( from route in RailwayContainer.Routes @@ -556,7 +556,7 @@ from route in RailwayContainer.Routes let routeString = route.ToString() select routeEntry + routeString); - //DmglVisualizer.OpenDgml(); + //QueryExpressionDgmlVisualizer.OpenDgml(); var routeTest = RailwayContainer.Routes[0]; @@ -582,7 +582,7 @@ from route in RailwayContainer.Routes [TestMethod] public void NotifySystem_Optimize_SelectManySelect() { - //DmglVisualizer.Initialize(); + //QueryExpressionDgmlVisualizer.Initialize(); var func = CreateExpression( from route in RailwayContainer.Routes @@ -592,7 +592,7 @@ from swP in route.Follows.OfType() select swP.Position.ToString()); //select swP.Position.ToString()); - //DmglVisualizer.OpenDgml(); + //QueryExpressionDgmlVisualizer.OpenDgml(); var routeTest = RailwayContainer.Routes[0]; From 37fac2366b71ab83423ac99df57a48b3c9b71cfc Mon Sep 17 00:00:00 2001 From: marcu Date: Wed, 7 Mar 2018 16:34:12 +0100 Subject: [PATCH 06/10] algorithmus in selectExpression.asOptimized method simplified; --- .../GroupJoinExpression.cs | 5 ++-- .../EnumerableExpressions/JoinExpression.cs | 5 ++-- .../EnumerableExpressions/SelectExpression.cs | 29 ++++--------------- .../SelectManyExpression.cs | 5 ++-- .../Facade/OptimizableExpressionExtensions.cs | 16 +++++----- 5 files changed, 23 insertions(+), 37 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index 616638f8a..e95821706 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -75,8 +75,9 @@ public IEnumerableExpression AsOptimized(IOp #if DEBUG VisitForDebugging(ResultSelector); #endif - - return this.Merge(expression); + if (expression != null) + return Merge(expression); + return (IEnumerableExpression)this; } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index 56dbbb21d..fd6c89910 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -81,8 +81,9 @@ public IEnumerableExpression AsOptimized(IOp #if DEBUG VisitForDebugging(ResultSelector); #endif - - return Merge(expression); + if (expression != null) + return Merge(expression); + return (IEnumerableExpression)this; } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 4197cbaeb..abf80fb44 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -70,33 +70,14 @@ public IEnumerableExpression AsOptimized(IOp VisitForDebugging(SelectorExpression); #endif - //TODO: Aufruf hier weglassen - IEnumerableExpression optimizedExpression = this.Optimize(Source); - - //Wenn expression == null : Ausgangspunkt der Optimierung - if (expression != null) + if (this.IsOptimizable(Source)) { - //TODO: Hier eine IsOptimizable() Methode in einem if aufrufen (prüft nur den Typ) - - //TODO: Dadurch kann man sich die Überprüfung mit != this sparen - //if return value of optimize() is the caller of this method - //nothing can be optimized - if (optimizedExpression != this) - { - - //TODO: Dann hier erst Optimize Extension Method Aufrufen und den Rückgabetyp ändern um anschließenden Cast zu sparen - //TODO: bzw. wieso muss man hier nochmal AsOptimized aufrufen? Wurde doch oben in der Optimize ExtMethod gemacht wenn Typ passt! - - //test != this: eine bereit neu erstellte Expression soll weiter optimiert werden - var castedOptimizedExpression = optimizedExpression as IOptimizableEnumerableExpression; - return castedOptimizedExpression.AsOptimized(expression); - } - - //Create new Expression - return Merge(expression); + return this.Optimize(Source as IOptimizableEnumerableExpression).AsOptimized(expression); } - return (IEnumerableExpression)optimizedExpression; + if(expression != null) + return Merge(expression); + return (IEnumerableExpression) this; } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index 6957e3fb4..ceb4b64e9 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -66,8 +66,9 @@ public IEnumerableExpression AsOptimized(IOp #if DEBUG VisitForDebugging(ResultSelector); #endif - - return this.Merge(expression); + if(expression != null) + return Merge(expression); + return (IEnumerableExpression) this; } public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs index 55caca44e..c805627a2 100644 --- a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs +++ b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs @@ -10,14 +10,16 @@ namespace NMF.Expressions.Linq /// internal static class OptimizableEnumerableExpressionExtensions { - internal static IEnumerableExpression Optimize(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) + internal static bool IsOptimizable(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) { - if (source is IOptimizableEnumerableExpression) - { - var castedSource = source as IOptimizableEnumerableExpression; - return castedSource.AsOptimized(optimizableEnumerableExpression); ; - } - return (IEnumerableExpression)optimizableEnumerableExpression; + if (source is IOptimizableEnumerableExpression) + return true; + return false; + } + + internal static IOptimizableEnumerableExpression Optimize(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IOptimizableEnumerableExpression source) + { + return (IOptimizableEnumerableExpression) source.AsOptimized(optimizableEnumerableExpression); } } } \ No newline at end of file From de3ffe84cc6ebc35aad5e178092cd488d7dfc845 Mon Sep 17 00:00:00 2001 From: marcu Date: Thu, 8 Mar 2018 13:09:20 +0100 Subject: [PATCH 07/10] some renaming --- .../GroupJoinExpression.cs | 2 +- .../EnumerableExpressions/JoinExpression.cs | 2 +- .../EnumerableExpressions/SelectExpression.cs | 21 ++++++++----------- .../SelectManyExpression.cs | 2 +- .../Facade/IEnumerableExpression.cs | 6 +++--- .../Facade/OptimizableExpressionExtensions.cs | 2 +- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index e95821706..edf641ade 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -86,7 +86,7 @@ public IEnumerableExpression Merge(IOptimiza return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - private void VisitForDebugging(dynamic expression) + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen DebugVisitor debugVisitor = new DebugVisitor(); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index fd6c89910..eef277922 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -92,7 +92,7 @@ public IEnumerableExpression Merge(IOptimiza return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } - private void VisitForDebugging(dynamic expression) + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen DebugVisitor debugVisitor = new DebugVisitor(); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index abf80fb44..39cb33424 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -29,13 +29,11 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() { - //TODO: Wie oben erst eine IsOptimizable Methode aufrufen und falls true Optimize aufrufen. Dadurch spart man sich hier wieder den != this Vergleich IEnumerableExpression optimizedExpression = AsOptimized(); if (optimizedExpression != this) @@ -64,29 +62,28 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() return AsNotifiable(); } - public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null) + public IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression prevOptExpression = null) { #if DEBUG VisitForDebugging(SelectorExpression); #endif - if (this.IsOptimizable(Source)) - { - return this.Optimize(Source as IOptimizableEnumerableExpression).AsOptimized(expression); - } + if (this.IsSourceOptimizable(Source)) + return this.Optimize(Source as IOptimizableEnumerableExpression).AsOptimized(prevOptExpression); + + if(prevOptExpression != null) + return Merge(prevOptExpression); - if(expression != null) - return Merge(expression); return (IEnumerableExpression) this; } - public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) + public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevOptExpression) { - var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; + var mergedSelectorExpression = QueryOptimizer.Optimize(prevOptExpression.OptSelectorExpression, OptSelectorExpression) as Expression>; return new SelectExpression(Source, mergedSelectorExpression, null); } - private void VisitForDebugging(dynamic expression) + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen DebugVisitor debugVisitor = new DebugVisitor(); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index ceb4b64e9..4c691be64 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -77,7 +77,7 @@ public IEnumerableExpression Merge(IOptimiza return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); } - private void VisitForDebugging(dynamic expression) + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen DebugVisitor debugVisitor = new DebugVisitor(); diff --git a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs index cdd18adac..5ea3ca969 100644 --- a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs +++ b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs @@ -18,11 +18,11 @@ internal interface IOptimizableEnumerableExpression /// Gets optimization for this collection /// /// - /// + /// /// - IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression expression = null); + IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression prevOptExpression = null); - IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr); + IEnumerableExpression Merge(IOptimizableEnumerableExpression prevOptExpression); } /// diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs index c805627a2..2fc1a3f1c 100644 --- a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs +++ b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs @@ -10,7 +10,7 @@ namespace NMF.Expressions.Linq /// internal static class OptimizableEnumerableExpressionExtensions { - internal static bool IsOptimizable(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) + internal static bool IsSourceOptimizable(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) { if (source is IOptimizableEnumerableExpression) return true; From 816b2a4ddaeb26fc4ebcb5b8ebb3c6692578ec56 Mon Sep 17 00:00:00 2001 From: marcu Date: Fri, 9 Mar 2018 14:36:50 +0100 Subject: [PATCH 08/10] use is type pattern expression --- .../DynamicDependencyGraphDgmlVisualizer.cs | 2 +- .../EnumerableExpressions/SelectExpression.cs | 4 ++-- .../Facade/OptimizableExpressionExtensions.cs | 7 ------- .../Tests/Models.Expressions.Tests/NotifySystemTests.cs | 3 ++- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs index 9481298b4..acb0248c0 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DynamicDependencyGraphDgmlVisualizer.cs @@ -69,7 +69,7 @@ private static void OpenDgml(XDocument doc) var fileName = DateTime.Now.ToString("hh-mm-ss") + ".dgml"; var filePath = Path.Combine(Path.GetTempPath(), fileName); doc.Save(filePath); - System.Diagnostics.Process.Start(filePath); + //System.Diagnostics.Process.Start(filePath); } private static XDocument CreateDgmlDoc() diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 39cb33424..3728881af 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -68,8 +68,8 @@ public IEnumerableExpression AsOptimized(IOp VisitForDebugging(SelectorExpression); #endif - if (this.IsSourceOptimizable(Source)) - return this.Optimize(Source as IOptimizableEnumerableExpression).AsOptimized(prevOptExpression); + if (Source is IOptimizableEnumerableExpression source) + return this.Optimize(source).AsOptimized(prevOptExpression); if(prevOptExpression != null) return Merge(prevOptExpression); diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs index 2fc1a3f1c..d038c2b5f 100644 --- a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs +++ b/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs @@ -10,13 +10,6 @@ namespace NMF.Expressions.Linq /// internal static class OptimizableEnumerableExpressionExtensions { - internal static bool IsSourceOptimizable(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IEnumerableExpression source) - { - if (source is IOptimizableEnumerableExpression) - return true; - return false; - } - internal static IOptimizableEnumerableExpression Optimize(this IOptimizableEnumerableExpression optimizableEnumerableExpression, IOptimizableEnumerableExpression source) { return (IOptimizableEnumerableExpression) source.AsOptimized(optimizableEnumerableExpression); diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index aa1e06b24..a94ebe2d2 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -9,6 +9,7 @@ using System.Collections.Specialized; using System.Linq; using System.Text; +using NMF.Expressions.EnumerableExpressions; namespace NMF.Expressions.Tests { @@ -519,7 +520,7 @@ public void NotifySystem_Optimize_SelectSelect() //from swP in route.Follows.OfType() //where swP.Switch.CurrentPosition != swP.Position let routeString = route.ToString() - select route.ToIdentifierString() + routeString); + select route.ToIdentifierString() + routeString + routeString); //QueryExpressionDgmlVisualizer.OpenDgml(); From e3c9a3920594dd397e9716dd1c1efe8a62c0037f Mon Sep 17 00:00:00 2001 From: marcu Date: Sun, 25 Mar 2018 00:02:56 +0100 Subject: [PATCH 09/10] changes after codereview; --- .../EnumerableExpressions/CastExpression.cs | 4 +- .../EnumerableExpressions/ConcatExpression.cs | 4 +- .../DistinctExpression.cs | 4 +- .../EnumerableExpressions/ExceptExpression.cs | 4 +- .../GroupByExpression.cs | 7 +- .../GroupJoinExpression.cs | 14 +- .../EnumerableExpressions/JoinExpression.cs | 15 +- .../EnumerableExpressions/OfTypeExpression.cs | 5 +- .../OrderByExpression.cs | 6 +- .../EnumerableExpressions/QueryOptimizer.cs | 80 ------- .../EnumerableExpressions/SelectExpression.cs | 22 +- .../SelectManyExpression.cs | 14 +- .../SimpleSelectManyExpression.cs | 6 +- .../EnumerableExpressions/ThenByExpression.cs | 6 +- .../EnumerableExpressions/WhereExpression.cs | 5 +- .../IQueryOptimizer.cs | 15 ++ .../OptimizableExpressionExtensions.cs | 0 .../ProjectionMergeQueryOptimizer.cs | 209 ++++++++++++++++++ .../ExpressionsOptimization/QueryOptimizer.cs | 38 ++++ .../QueryOptimizerVisitor.cs | 0 .../Facade/IEnumerableExpression.cs | 45 +++- .../Expressions.Linq/Linq/ObservableGroup.cs | 4 + .../TreeExtensionNotifySystem.cs | 5 +- .../Expressions.Linq.Net45.csproj | 18 +- .../NotifySystemTests.cs | 2 +- 25 files changed, 420 insertions(+), 112 deletions(-) delete mode 100644 Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs create mode 100644 Expressions/Expressions.Linq/ExpressionsOptimization/IQueryOptimizer.cs rename Expressions/Expressions.Linq/{Facade => ExpressionsOptimization}/OptimizableExpressionExtensions.cs (100%) create mode 100644 Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs create mode 100644 Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizer.cs rename Expressions/Expressions.Linq/{EnumerableExpressions => ExpressionsOptimization}/QueryOptimizerVisitor.cs (100%) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/CastExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/CastExpression.cs index 9714414ed..10f4ba060 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/CastExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/CastExpression.cs @@ -7,11 +7,13 @@ namespace NMF.Expressions { - internal class CastExpression : IEnumerableExpression + internal class CastExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } private INotifyEnumerable notifyEnumerable; + public IEnumerableExpression OptSource => Source; + public CastExpression(IEnumerableExpression source) { if (source == null) throw new ArgumentNullException("source"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/ConcatExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/ConcatExpression.cs index 710748cf9..dfd8d1a0f 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/ConcatExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/ConcatExpression.cs @@ -7,12 +7,14 @@ namespace NMF.Expressions { - internal class ConcatExpression : IEnumerableExpression + internal class ConcatExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } public IEnumerable Other { get; private set; } private INotifyEnumerable notifyEnumerable; + public IEnumerableExpression OptSource => Source; + public ConcatExpression(IEnumerableExpression source, IEnumerable other) { if (source == null) throw new ArgumentNullException("source"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/DistinctExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/DistinctExpression.cs index 984355605..558f9fe35 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/DistinctExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/DistinctExpression.cs @@ -7,12 +7,14 @@ namespace NMF.Expressions { - internal class DistinctExpression : IEnumerableExpression + internal class DistinctExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } public IEqualityComparer Comparer { get; set; } private INotifyEnumerable notifyEnumerable; + public IEnumerableExpression OptSource => Source; + public DistinctExpression(IEnumerableExpression source, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/ExceptExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/ExceptExpression.cs index 886e09f0b..6da185598 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/ExceptExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/ExceptExpression.cs @@ -7,13 +7,15 @@ namespace NMF.Expressions { - internal abstract class SetExpression : IEnumerableExpression + internal abstract class SetExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } public IEnumerable Other { get; private set; } public IEqualityComparer Comparer { get; private set; } protected INotifyEnumerable notifyEnumerable; + public IEnumerableExpression OptSource => Source; + public SetExpression(IEnumerableExpression source, IEnumerable other, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupByExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupByExpression.cs index b2ecba674..b7e20d25b 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupByExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupByExpression.cs @@ -9,7 +9,7 @@ namespace NMF.Expressions { - internal class GroupByExpression : IEnumerableExpression> + internal class GroupByExpression : IEnumerableExpression>, ISQO { private class GroupingExpression : IGroupingExpression { @@ -37,6 +37,7 @@ public INotifyEnumerable AsNotifiable() groupBy.CreateIncremental(); return groupBy.notifyEnumerable[Key]; } + public IEnumerableExpression OptSource => throw new InvalidOperationException(); IEnumerator IEnumerable.GetEnumerator() { @@ -51,6 +52,10 @@ INotifyEnumerable IEnumerableExpression.AsNotifiable() public IEnumerableExpression Source { get; private set; } + + public IEnumerableExpression OptSource => Source; + + public Expression> Predicate { get; private set; } public Func PredicateCompiled { get; private set; } public IEqualityComparer Comparer { get; private set; } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs index edf641ade..5486f5c2b 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/GroupJoinExpression.cs @@ -8,7 +8,7 @@ namespace NMF.Expressions { - internal class GroupJoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression + internal class GroupJoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -23,6 +23,11 @@ internal class GroupJoinExpression : IEnumerableE public Expression OptSelectorExpression => ResultSelector; + public Expression PrevExpression { get; set; } + + public IEnumerableExpression OptSource => Source; + + public GroupJoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression, TResult>> resultSelector, Func, TResult> resultSelectorCompiled, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); @@ -82,10 +87,15 @@ public IEnumerableExpression AsOptimized(IOp public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression, TOptimizedResult>>; + var mergedSelectorExpression = new ProjectionMergeQueryOptimizer().Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression, TOptimizedResult>>; return new GroupJoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } + IOptimizableEnumerableExpression IOptimizableEnumerableExpression.AsOptimized2(IQueryOptimizer queryOptimizer) + { + return (IOptimizableEnumerableExpression)queryOptimizer.OptimizeExpression(this); + } + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs index eef277922..f7ce7fedc 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/JoinExpression.cs @@ -8,7 +8,7 @@ namespace NMF.Expressions { - internal class JoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression + internal class JoinExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; set; } public IEnumerable Inner { get; set; } @@ -21,7 +21,12 @@ internal class JoinExpression : IEnumerableExpres public IEqualityComparer Comparer { get; set; } private INotifyEnumerable notifyEnumerable; + + public IEnumerableExpression OptSource => Source; + + public Expression OptSelectorExpression => ResultSelector; + public Expression PrevExpression { get; set; } public JoinExpression(IEnumerableExpression outer, IEnumerable inner, Expression> outerKeySelector, Func outerKeySelectorCompiled, Expression> innerKeySelector, Func innerKeySelectorCompiled, Expression> resultSelector, Func resultSelectorCompiled, IEqualityComparer comparer) { @@ -88,10 +93,16 @@ public IEnumerableExpression AsOptimized(IOp public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; + var mergedSelectorExpression = new ProjectionMergeQueryOptimizer().Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; return new JoinExpression(Source, Inner, OuterKeySelector, null, InnerKeySelector, null, mergedSelectorExpression, null, Comparer); } + IOptimizableEnumerableExpression IOptimizableEnumerableExpression.AsOptimized2(IQueryOptimizer queryOptimizer) + { + return (IOptimizableEnumerableExpression)queryOptimizer.OptimizeExpression(this); + } + + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/OfTypeExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/OfTypeExpression.cs index 5e5bdd579..7f47d2708 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/OfTypeExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/OfTypeExpression.cs @@ -9,11 +9,14 @@ namespace NMF.Expressions { - internal class OfTypeExpression : IEnumerableExpression + internal class OfTypeExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } private INotifyEnumerable notifyEnumerable; + public IEnumerableExpression OptSource => Source; + + public OfTypeExpression(IEnumerableExpression source) { if (source == null) throw new ArgumentNullException("source"); diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/OrderByExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/OrderByExpression.cs index d2d29243b..75828c061 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/OrderByExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/OrderByExpression.cs @@ -7,9 +7,13 @@ namespace NMF.Expressions { - internal class OrderByExpression : IOrderableEnumerableExpression + internal class OrderByExpression : IOrderableEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } + + public IEnumerableExpression OptSource => Source; + + public Expression> Predicate { get; private set; } public Func PredicateCompiled { get; private set; } public IComparer Comparer { get; private set; } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs b/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs deleted file mode 100644 index 393a2f331..000000000 --- a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizer.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace NMF.Expressions -{ - /// - /// Implements query optimization approaches - /// - public static class QueryOptimizer - { - /// - /// Optimization of two consecutive expressions into one - /// - /// Source type of firstExpression and Source Type of merged expression - /// Result type of firstExpression - /// Result type of secondExpression and Result Type of merged expression - /// In the query evaluation earlier occurring expression - /// In the query evaluation appearing expression after firstExpression - /// - public static Expression Optimize(Expression firstExpression, Expression secondExpression) - { - return MergeLambdaExpressions(firstExpression as LambdaExpression, secondExpression as LambdaExpression); - //return MergeLambdaExpressionsWithVariables(firstExpression as LambdaExpression, secondExpression as LambdaExpression); - } - - /// - /// Merging two expressions by inserting secondLambdaExpression into firstLambdaExpression - /// - /// - /// - /// - public static Expression MergeLambdaExpressions(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) - { - var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression); - var builtExpression = queryOptimizerVisitor.Visit(firstLambdaExpression) as LambdaExpression; - return Expression.Lambda(builtExpression.Body, secondLambdaExpression.Parameters); - } - - /// - /// Merging two expressions by introducing a variable that represents the second expression - /// - /// Parameter type of firstLambdaExpression and Parameter type of merged expression - /// Result type of firstLambdaExpression - /// Result type of secondLambdaExpression and Result Type of merged expression - /// - /// - /// - public static Expression MergeLambdaExpressionsWithVariables(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) - { - var introduceOptimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); - var evaluateMethodInfo = typeof(ObservingFunc).GetMethod("Evaluate", new[] { typeof(TSource), typeof(TResult) }); - - var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression) - { - OptimizationVaribable = introduceOptimizationVaribable - }; - - //TODO: Methode schwer verständlich. Kann man kleinere Untermethoden erstellen die beschreibenden Namen haben? - - //Lambda expression that contains the second expression as a parameter. After visit that expression new parameter is used - var introduceOptimizationExpr = queryOptimizerVisitor.Visit(Expression.Lambda(firstLambdaExpression.Body, secondLambdaExpression.Parameters[0], introduceOptimizationVaribable)); - - return Expression.Lambda( - Expression.Call( - Expression.Constant( - new ObservingFunc( - introduceOptimizationExpr as Expression>) - ), - evaluateMethodInfo, - secondLambdaExpression.Parameters[0], - secondLambdaExpression.Body - ), - secondLambdaExpression.Parameters - ); - } - } -} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 3728881af..10319e3b1 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -9,7 +9,7 @@ namespace NMF.Expressions { - internal class SelectExpression : IEnumerableExpression, IOptimizableEnumerableExpression + internal class SelectExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression> SelectorExpression { get; private set; } @@ -17,6 +17,11 @@ internal class SelectExpression : IEnumerableExpression notifyEnumerable; public Expression OptSelectorExpression => SelectorExpression; + public Expression PrevExpression { get; set; } + + public IEnumerableExpression OptSource => Source; + + public SelectExpression(IEnumerableExpression source, Expression> selector, Func selectorCompiled) { @@ -34,7 +39,13 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() { - IEnumerableExpression optimizedExpression = AsOptimized(); + //IEnumerableExpression optimizedExpression = AsOptimized(); + + //if (optimizedExpression != this) + // return optimizedExpression.AsNotifiable(); + + //IEnumerableExpression optimizedExpression = QueryOptimizer.DefaultQueryOptimizer.OptimizeExpression(this) as IEnumerableExpression; + IEnumerableExpression optimizedExpression = QueryOptimizer.DefaultQueryOptimizer.Optimize(this) as IEnumerableExpression; if (optimizedExpression != this) return optimizedExpression.AsNotifiable(); @@ -79,10 +90,15 @@ public IEnumerableExpression AsOptimized(IOp public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevOptExpression) { - var mergedSelectorExpression = QueryOptimizer.Optimize(prevOptExpression.OptSelectorExpression, OptSelectorExpression) as Expression>; + var mergedSelectorExpression = new ProjectionMergeQueryOptimizer().Optimize(prevOptExpression.OptSelectorExpression, OptSelectorExpression) as Expression>; return new SelectExpression(Source, mergedSelectorExpression, null); } + IOptimizableEnumerableExpression IOptimizableEnumerableExpression.AsOptimized2(IQueryOptimizer queryOptimizer) + { + return queryOptimizer.OptimizeExpression(this); + } + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs index 4c691be64..192391fdc 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectManyExpression.cs @@ -9,7 +9,7 @@ namespace NMF.Expressions { - internal class SelectManyExpression : IEnumerableExpression, IOptimizableEnumerableExpression + internal class SelectManyExpression : IEnumerableExpression, IOptimizableEnumerableExpression { public IEnumerableExpression Source { get; private set; } public Expression>> FuncExpression { get; private set; } @@ -20,6 +20,11 @@ internal class SelectManyExpression : IEnumerab public Expression OptSelectorExpression => ResultSelector; + public IEnumerableExpression OptSource => Source; + + + public Expression PrevExpression { get; set; } + public SelectManyExpression(IEnumerableExpression source, Expression>> func, Func> funcCompiled, Expression> resultSelector, Func resultSelectorCompiled) { if (source == null) throw new ArgumentNullException("source"); @@ -73,10 +78,15 @@ public IEnumerableExpression AsOptimized(IOp public IEnumerableExpression Merge(IOptimizableEnumerableExpression prevExpr) { - var mergedSelectorExpression = QueryOptimizer.Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; + var mergedSelectorExpression = new ProjectionMergeQueryOptimizer().Optimize(prevExpr.OptSelectorExpression, OptSelectorExpression) as Expression>; return new SelectManyExpression(Source, FuncExpression, null, mergedSelectorExpression, null); } + IOptimizableEnumerableExpression IOptimizableEnumerableExpression.AsOptimized2(IQueryOptimizer queryOptimizer) + { + return queryOptimizer.OptimizeExpression(this); + } + private void VisitForDebugging(Expression expression) { //Ausgabe überprüfen diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SimpleSelectManyExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SimpleSelectManyExpression.cs index c253a7982..75c17d047 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SimpleSelectManyExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SimpleSelectManyExpression.cs @@ -8,9 +8,13 @@ namespace NMF.Expressions { - internal class SimpleSelectManyExpression : IEnumerableExpression + internal class SimpleSelectManyExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } + + public IEnumerableExpression OptSource => Source; + + public Expression>> SelectorExpression { get; private set; } public Func> SelectorCompiled { get; private set; } private INotifyEnumerable notifyEnumerable; diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/ThenByExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/ThenByExpression.cs index b79a81eab..01a13a3a9 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/ThenByExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/ThenByExpression.cs @@ -8,9 +8,13 @@ namespace NMF.Expressions { - internal class ThenByExpression : IOrderableEnumerableExpression + internal class ThenByExpression : IOrderableEnumerableExpression, ISQO { public IOrderableEnumerableExpression Source { get; private set; } + + public IEnumerableExpression OptSource => Source; + + public Expression> Predicate { get; private set; } public Func PredicateCompiled { get; private set; } public IComparer Comparer { get; private set; } diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/WhereExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/WhereExpression.cs index fb3ce9977..4c210b605 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/WhereExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/WhereExpression.cs @@ -10,9 +10,12 @@ namespace NMF.Expressions { - internal class WhereExpression : IEnumerableExpression + internal class WhereExpression : IEnumerableExpression, ISQO { public IEnumerableExpression Source { get; private set; } + + public IEnumerableExpression OptSource => Source; + public Expression> PredicateExpression { get; private set; } public Func PredicateCompiled { get; private set; } private INotifyEnumerable notifyEnumerable; diff --git a/Expressions/Expressions.Linq/ExpressionsOptimization/IQueryOptimizer.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/IQueryOptimizer.cs new file mode 100644 index 000000000..100537dba --- /dev/null +++ b/Expressions/Expressions.Linq/ExpressionsOptimization/IQueryOptimizer.cs @@ -0,0 +1,15 @@ +namespace NMF.Expressions +{ + internal interface IQueryOptimizer + { + IEnumerableExpression Optimize(ISQO expression); + + IOptimizableEnumerableExpression OptimizeExpression(SelectExpression expression); + + IOptimizableEnumerableExpression OptimizeExpression(SelectManyExpression expression); + + IOptimizableEnumerableExpression OptimizeExpression(JoinExpression expression); + + IOptimizableEnumerableExpression OptimizeExpression(GroupJoinExpression expression); + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/OptimizableExpressionExtensions.cs similarity index 100% rename from Expressions/Expressions.Linq/Facade/OptimizableExpressionExtensions.cs rename to Expressions/Expressions.Linq/ExpressionsOptimization/OptimizableExpressionExtensions.cs diff --git a/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs new file mode 100644 index 000000000..822c3f4a2 --- /dev/null +++ b/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using NMF.Utilities; + +namespace NMF.Expressions +{ + /// + /// Implements query optimization approaches + /// + internal class ProjectionMergeQueryOptimizer : IQueryOptimizer + { + private static Type[] promotionMethodCallTypes = + { + typeof(ObservingFunc<,>), + typeof(ObservingFunc<,,>), + typeof(ObservingFunc<,,,>), + typeof(ObservingFunc<,,,,>), + typeof(ObservingFunc<,,,,,>), + typeof(ObservingFunc<,,,,,,>), + typeof(ObservingFunc<,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,,,,,>), + typeof(ObservingFunc<,,,,,,,,,,,,,,,>) + }; + + + /// + /// Optimization of two consecutive expressions into one + /// + /// Source type of firstExpression and Source Type of merged expression + /// Result type of firstExpression + /// Result type of secondExpression and Result Type of merged expression + /// In the query evaluation earlier occurring expression + /// In the query evaluation appearing expression after firstExpression + /// + public Expression Optimize(Expression firstExpression, Expression secondExpression) + { + //return MergeLambdaExpressions(firstExpression as LambdaExpression, secondExpression as LambdaExpression); + return MergeLambdaExpressionsWithVariables(firstExpression as LambdaExpression, secondExpression as LambdaExpression); + } + + /// + /// Merging two expressions by inserting secondLambdaExpression into firstLambdaExpression + /// + /// + /// + /// + public Expression MergeLambdaExpressions(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) + { + var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression); + var builtExpression = queryOptimizerVisitor.Visit(firstLambdaExpression) as LambdaExpression; + return Expression.Lambda(builtExpression.Body, secondLambdaExpression.Parameters); + } + + /// + /// Merging two expressions by introducing a variable that represents the second expression + /// + /// Parameter type of firstLambdaExpression and Parameter type of merged expression + /// Result type of firstLambdaExpression + /// Result type of secondLambdaExpression and Result Type of merged expression + /// + /// + /// + public Expression MergeLambdaExpressionsWithVariables(LambdaExpression firstLambdaExpression, LambdaExpression secondLambdaExpression) + { + var introduceOptimizationVaribable = Expression.Parameter(typeof(TResult), "optimization_arg"); + var evaluateMethodArgs = new Expression[secondLambdaExpression.Parameters.Count + 1]; + var queryOptimizerVisitor = new QueryOptimizerVisitor(firstLambdaExpression, secondLambdaExpression) + { + OptimizationVaribable = introduceOptimizationVaribable + }; + + var parametersWithOptimizationVariable = new ParameterExpression[secondLambdaExpression.Parameters.Count + 1]; + for (int i = 0; i < secondLambdaExpression.Parameters.Count; i++) + parametersWithOptimizationVariable[i] = secondLambdaExpression.Parameters[i]; + + parametersWithOptimizationVariable[secondLambdaExpression.Parameters.Count] = introduceOptimizationVaribable; + + var introduceOptimizationExpr = queryOptimizerVisitor.Visit(Expression.Lambda(firstLambdaExpression.Body, parametersWithOptimizationVariable)); + + for (int i = 0; i < secondLambdaExpression.Parameters.Count; i++) + { + evaluateMethodArgs[i] = secondLambdaExpression.Parameters[i]; + } + evaluateMethodArgs[secondLambdaExpression.Parameters.Count] = secondLambdaExpression.Body; + + Type[] genericTypeArgumentsOfExprOfFunc = introduceOptimizationExpr.GetType().GetGenericArguments()[0].GenericTypeArguments; + Type[] genericTypeArgumentsOfExprOfFuncWithoutResultType = new Type[genericTypeArgumentsOfExprOfFunc.Length - 1]; + Array.Copy(genericTypeArgumentsOfExprOfFunc, 0, genericTypeArgumentsOfExprOfFuncWithoutResultType, 0, genericTypeArgumentsOfExprOfFunc.Length - 1); + + + var observingFunc = CreateObservingFunc(genericTypeArgumentsOfExprOfFunc, introduceOptimizationExpr); + var evaluateMethodInfo = observingFunc.GetType().GetMethod("Evaluate", genericTypeArgumentsOfExprOfFuncWithoutResultType); + + return Expression.Lambda( + Expression.Call( + Expression.Constant( + observingFunc + ), + evaluateMethodInfo, + evaluateMethodArgs + ), + secondLambdaExpression.Parameters + ); + } + + public T CastExamp1(object input) + { + return (T)input; + } + + private object CreateObservingFunc(Type[] types, dynamic introduceOptimizationExpr) + { + var promotionMethodCallType = promotionMethodCallTypes[types.Length-2].MakeGenericType(types); + var constructor = promotionMethodCallType.GetConstructors()[0]; + + MethodInfo castMethod = this.GetType().GetMethod("CastExamp1").MakeGenericMethod(introduceOptimizationExpr.GetType()); + object castedObject = castMethod.Invoke(this, new object[] { introduceOptimizationExpr }); + + return constructor.Invoke(new[] {castedObject}); + } + + public IOptimizableEnumerableExpression OptimizeExpression(IOptimizableEnumerableExpression expression) + { + + + if(expression.PrevExpression != null) + return expression.AsOptimized2(this); + return expression; + } + + public IEnumerableExpression Optimize(ISQO expression) + { + if (expression is IOptimizableEnumerableExpression opt && expression.OptSource is IOptimizableEnumerableExpression optSource) + { +#if DEBUG + VisitForDebugging(opt.OptSelectorExpression); +#endif + optSource.PrevExpression = opt.OptSelectorExpression; + var test = optSource.AsOptimized2(this); + return Optimize(test); + } + + return (IEnumerableExpression)expression; + } + + public IOptimizableEnumerableExpression OptimizeExpression(SelectExpression expression) + { +#if DEBUG + VisitForDebugging(expression.SelectorExpression); +#endif + var mergedSelectorExpression = this.Optimize(expression.PrevExpression, expression.SelectorExpression) as Expression>; + return new SelectExpression(expression.Source, mergedSelectorExpression, null); + } + + public IOptimizableEnumerableExpression OptimizeExpression(SelectManyExpression expression) + { +#if DEBUG + VisitForDebugging(expression.ResultSelector); +#endif + if (expression.PrevExpression == null) + throw new ArgumentNullException("expression.PrevExpression"); + + var mergedSelectorExpression = this.Optimize(expression.PrevExpression,expression.ResultSelector) as Expression>; + return new SelectManyExpression(expression.Source, expression.FuncExpression, null, mergedSelectorExpression, null); + } + + public IOptimizableEnumerableExpression OptimizeExpression(JoinExpression expression) + { +#if DEBUG + VisitForDebugging(expression.ResultSelector); +#endif + if (expression.PrevExpression == null) + throw new ArgumentNullException("expression.PrevExpression"); + + var mergedSelectorExpression = this.Optimize(expression.PrevExpression, expression.ResultSelector) as Expression>; + return new JoinExpression(expression.Source, expression.Inner, expression.OuterKeySelector, null, expression.InnerKeySelector, null, mergedSelectorExpression, null, expression.Comparer); + } + + public IOptimizableEnumerableExpression OptimizeExpression(GroupJoinExpression expression) + { +#if DEBUG + VisitForDebugging(expression.ResultSelector); +#endif + if (expression.PrevExpression == null) + throw new ArgumentNullException("expression.PrevExpression"); + + var mergedSelectorExpression = this.Optimize(expression.PrevExpression, expression.ResultSelector) as Expression, TOptimizedResult>>; + return new GroupJoinExpression(expression.Source, expression.Inner, expression.OuterKeySelector, null, expression.InnerKeySelector, null, mergedSelectorExpression, null, expression.Comparer); + } + + private void VisitForDebugging(Expression expression) + { + //Ausgabe überprüfen + DebugVisitor debugVisitor = new DebugVisitor(); + debugVisitor.Visit(expression); + } + + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizer.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizer.cs new file mode 100644 index 000000000..c2daf7e57 --- /dev/null +++ b/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizer.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace NMF.Expressions +{ + /// + /// This class encapsulates a default query optimizer + /// + static class QueryOptimizer + { + static QueryOptimizer() + { + defaultQueryOptimizer = new ProjectionMergeQueryOptimizer(); + } + + private static IQueryOptimizer defaultQueryOptimizer; + + /// + /// Gets or sets the incremental computation system to be used by default + /// + /// This property can never be set to a null value + public static IQueryOptimizer DefaultQueryOptimizer + { + get + { + return defaultQueryOptimizer; + } + set + { + defaultQueryOptimizer = value ?? defaultQueryOptimizer; + } + } + } +} \ No newline at end of file diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs similarity index 100% rename from Expressions/Expressions.Linq/EnumerableExpressions/QueryOptimizerVisitor.cs rename to Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs diff --git a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs index 5ea3ca969..4c9ef4ed4 100644 --- a/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs +++ b/Expressions/Expressions.Linq/Facade/IEnumerableExpression.cs @@ -7,13 +7,17 @@ namespace NMF.Expressions { - /// - /// Represents a collection that can be optimized - /// - internal interface IOptimizableEnumerableExpression + internal interface ISQO + { + IEnumerableExpression OptSource { get; } + } + + internal interface IOptimizableEnumerableExpression : ISQO { Expression OptSelectorExpression { get; } + Expression PrevExpression { set; get; } + /// /// Gets optimization for this collection /// @@ -23,6 +27,39 @@ internal interface IOptimizableEnumerableExpression IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression prevOptExpression = null); IEnumerableExpression Merge(IOptimizableEnumerableExpression prevOptExpression); + + IOptimizableEnumerableExpression AsOptimized2(IQueryOptimizer queryOptimizer); + } + + /// + /// Represents a collection that can be optimized + /// + internal interface IOptimizableEnumerableExpression : IOptimizableEnumerableExpression + { + /// + /// Gets optimization for this collection + /// + /// + /// + /// + //IEnumerableExpression AsOptimized(IOptimizableEnumerableExpression prevOptExpression = null); + + //IEnumerableExpression Merge(IOptimizableEnumerableExpression prevOptExpression); + } + + internal interface IOptimizableEnumerableExpression : IOptimizableEnumerableExpression + { + new IOptimizableEnumerableExpression AsOptimized2(IQueryOptimizer queryOptimizer); + } + + internal interface IOptimizableEnumerableExpression : IOptimizableEnumerableExpression + { + new IOptimizableEnumerableExpression AsOptimized2(IQueryOptimizer queryOptimizer); + } + + internal interface IOptimizableEnumerableExpression : IOptimizableEnumerableExpression + { + new IOptimizableEnumerableExpression AsOptimized2(IQueryOptimizer queryOptimizer); } /// diff --git a/Expressions/Expressions.Linq/Linq/ObservableGroup.cs b/Expressions/Expressions.Linq/Linq/ObservableGroup.cs index 8845702a8..c9167487d 100644 --- a/Expressions/Expressions.Linq/Linq/ObservableGroup.cs +++ b/Expressions/Expressions.Linq/Linq/ObservableGroup.cs @@ -18,6 +18,8 @@ public ObservableGroup(TKey key) { this.key = key; } + + public TKey Key { get { return key; } } @@ -32,6 +34,8 @@ public INotifyEnumerable AsNotifiable() return this; } + public IEnumerableExpression OptSource => throw new InvalidOperationException(); + INotifyEnumerable IEnumerableExpression.AsNotifiable() { return AsNotifiable(); diff --git a/Expressions/Models.Expressions/TreeExtensionNotifySystem.cs b/Expressions/Models.Expressions/TreeExtensionNotifySystem.cs index 5563583e8..821a4d0a9 100644 --- a/Expressions/Models.Expressions/TreeExtensionNotifySystem.cs +++ b/Expressions/Models.Expressions/TreeExtensionNotifySystem.cs @@ -66,8 +66,9 @@ private object CreateExpressionInternal(Expression expression, IEnumerable EnumerableExpressions\QueryExpressionDgmlVisualizer.cs - - EnumerableExpressions\QueryOptimizer.cs + + ExpressionsOptimization\ProjectionMergeQueryOptimizer.cs - - EnumerableExpressions\QueryOptimizerVisitor.cs + + ExpressionsOptimization\QueryOptimizer.cs + + + ExpressionsOptimization\QueryOptimizerVisitor.cs EnumerableExpressions\SelectExpression.cs @@ -112,8 +115,11 @@ Facade\ObservableExtensions.cs - - Facade\OptimizableExpressionExtensions.cs + + ExpressionsOptimization\OptimizableExpressionExtensions.cs + + + ExpressionsOptimization\OptimizableExpressionExtensions.cs Facade\OrderableList.cs diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index a94ebe2d2..f38b40a6a 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -599,7 +599,7 @@ from swP in route.Follows.OfType() var test = func.AsNotifiable(); - //DDGDgmlVisualizer.initDgmlVisualizer(test); + DDGDgmlVisualizer.initDgmlVisualizer(test); var resultChanged = false; test.CollectionChanged += (o, e) => From cbad85493535a89671db6bd9d2036aaacf69f7a8 Mon Sep 17 00:00:00 2001 From: marcu Date: Wed, 11 Apr 2018 12:49:17 +0200 Subject: [PATCH 10/10] bugfixes --- .../EnumerableExpressions/SelectExpression.cs | 6 - .../ProjectionMergeQueryOptimizer.cs | 4 +- .../QueryOptimizerVisitor.cs | 4 +- .../Expressions.Linq.Net45.csproj | 3 - .../NotifySystemTests.cs | 1 + NMF.sln | 554 +++++++++++++++++- 6 files changed, 528 insertions(+), 44 deletions(-) diff --git a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs index 10319e3b1..888a959a8 100644 --- a/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs +++ b/Expressions/Expressions.Linq/EnumerableExpressions/SelectExpression.cs @@ -39,12 +39,6 @@ public SelectExpression(IEnumerableExpression source, Expression AsNotifiable() { - //IEnumerableExpression optimizedExpression = AsOptimized(); - - //if (optimizedExpression != this) - // return optimizedExpression.AsNotifiable(); - - //IEnumerableExpression optimizedExpression = QueryOptimizer.DefaultQueryOptimizer.OptimizeExpression(this) as IEnumerableExpression; IEnumerableExpression optimizedExpression = QueryOptimizer.DefaultQueryOptimizer.Optimize(this) as IEnumerableExpression; if (optimizedExpression != this) diff --git a/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs index 822c3f4a2..8596dcdf0 100644 --- a/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs +++ b/Expressions/Expressions.Linq/ExpressionsOptimization/ProjectionMergeQueryOptimizer.cs @@ -44,8 +44,8 @@ internal class ProjectionMergeQueryOptimizer : IQueryOptimizer /// public Expression Optimize(Expression firstExpression, Expression secondExpression) { - //return MergeLambdaExpressions(firstExpression as LambdaExpression, secondExpression as LambdaExpression); - return MergeLambdaExpressionsWithVariables(firstExpression as LambdaExpression, secondExpression as LambdaExpression); + return MergeLambdaExpressions(firstExpression as LambdaExpression, secondExpression as LambdaExpression); + //return MergeLambdaExpressionsWithVariables(firstExpression as LambdaExpression, secondExpression as LambdaExpression); } /// diff --git a/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs b/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs index 9e5ca02e0..02df6cb41 100644 --- a/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs +++ b/Expressions/Expressions.Linq/ExpressionsOptimization/QueryOptimizerVisitor.cs @@ -1,4 +1,5 @@ -using System.Linq.Expressions; +using System.Linq; +using System.Linq.Expressions; using System.Runtime.CompilerServices; namespace NMF.Expressions @@ -18,6 +19,7 @@ public QueryOptimizerVisitor(LambdaExpression firstLambdaSelectorExpression, Lam protected override Expression VisitParameter(ParameterExpression node) { + var param = _firstLambdaSelectorExpression.Parameters[0]; if (node.ToString().Equals(param.ToString())) diff --git a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj index f3601442c..cf666faad 100644 --- a/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj +++ b/Expressions/Net45/Expressions.Linq.Net45/Expressions.Linq.Net45.csproj @@ -121,9 +121,6 @@ ExpressionsOptimization\OptimizableExpressionExtensions.cs - - Facade\OrderableList.cs - Linq\Multiplicity.cs diff --git a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs index f38b40a6a..71d5b5808 100644 --- a/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs +++ b/Expressions/Tests/Models.Expressions.Tests/NotifySystemTests.cs @@ -525,6 +525,7 @@ public void NotifySystem_Optimize_SelectSelect() //QueryExpressionDgmlVisualizer.OpenDgml(); var routeTest = RailwayContainer.Routes[0]; + var test = func.AsNotifiable(); //DDGDgmlVisualizer.initDgmlVisualizer(test); diff --git a/NMF.sln b/NMF.sln index 6cf93d902..67d4e003e 100644 --- a/NMF.sln +++ b/NMF.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 +VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analysis", "Analysis", "{DB96042F-8815-430D-8345-362F4266F0FE}" EndProject @@ -170,489 +170,982 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Synchronizations.Models", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Synchronizations.Models.Tests", "Synchronizations\Synchronizations.Models.Tests\Synchronizations.Models.Tests.csproj", "{4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Expressions.Utilities.Net45", "Expressions\Net45\Expressions.Utilities.Net45\Expressions.Utilities.Net45.csproj", "{95428F1D-8232-4360-86F8-727139E03426}" -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UserInterface", "UserInterface", "{6B587373-3C4C-4127-BFD1-DA9A89C0555B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrainBenchmarkNMF", "TrainBenchmarkNMF\TrainBenchmarkNMF.csproj", "{4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls", "UserInterfaces\Controls\Controls.csproj", "{7C5A3F03-57A3-4009-928A-6C0E1085FA09}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Expressions.Configuration", "..\NMF45\Expressions\Expressions.Configuration\Expressions.Configuration.csproj", "{502C1461-6DE2-4613-BBDB-96EDDFAC73E7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Editor", "UserInterfaces\Editor\Editor.csproj", "{CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Expressions.Models", "..\NMF45\Expressions\Models.Expressions\Expressions.Models.csproj", "{90CF2658-A5FE-4695-ABFC-FB10DD445379}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RayTracer", "..\raytracerneuneu\RayTracer.csproj", "{279B3B52-9CE6-4A65-B359-4894339A870A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Signed Debug|Any CPU = Signed Debug|Any CPU + Signed Debug|x64 = Signed Debug|x64 Signed Release|Any CPU = Signed Release|Any CPU + Signed Release|x64 = Signed Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Debug|x64.ActiveCfg = Debug|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Debug|x64.Build.0 = Debug|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Release|Any CPU.ActiveCfg = Release|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Release|Any CPU.Build.0 = Release|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Release|x64.ActiveCfg = Release|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Release|x64.Build.0 = Release|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Debug|x64.Build.0 = Debug|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Release|x64.ActiveCfg = Release|Any CPU + {A88B8AD4-1BE3-4E2B-B9E4-C1D34FF64E30}.Signed Release|x64.Build.0 = Release|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Debug|x64.ActiveCfg = Debug|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Debug|x64.Build.0 = Debug|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Release|Any CPU.Build.0 = Release|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Release|x64.ActiveCfg = Release|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Release|x64.Build.0 = Release|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Debug|x64.Build.0 = Debug|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Release|x64.ActiveCfg = Release|Any CPU + {6F57AA50-FB70-4DE8-BEAB-E3AE58B225D3}.Signed Release|x64.Build.0 = Release|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Debug|x64.ActiveCfg = Debug|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Debug|x64.Build.0 = Debug|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Release|Any CPU.ActiveCfg = Release|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Release|Any CPU.Build.0 = Release|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Release|x64.ActiveCfg = Release|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Release|x64.Build.0 = Release|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Debug|x64.Build.0 = Debug|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Release|x64.ActiveCfg = Release|Any CPU + {72A0A175-B9EC-4BEF-8C29-164C8C878A08}.Signed Release|x64.Build.0 = Release|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Debug|x64.ActiveCfg = Debug|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Debug|x64.Build.0 = Debug|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Release|Any CPU.Build.0 = Release|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Release|x64.ActiveCfg = Release|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Release|x64.Build.0 = Release|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Debug|x64.Build.0 = Debug|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Release|x64.ActiveCfg = Release|Any CPU + {DE054DF8-C249-4222-9EE7-A44B0442E0CD}.Signed Release|x64.Build.0 = Release|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Debug|x64.ActiveCfg = Debug|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Debug|x64.Build.0 = Debug|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Release|Any CPU.Build.0 = Release|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Release|x64.ActiveCfg = Release|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Release|x64.Build.0 = Release|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Debug|x64.Build.0 = Debug|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Release|x64.ActiveCfg = Release|Any CPU + {DC65E4BA-5983-47CB-8D6E-1947C7F15973}.Signed Release|x64.Build.0 = Release|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Debug|x64.Build.0 = Debug|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Release|Any CPU.Build.0 = Release|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Release|x64.ActiveCfg = Release|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Release|x64.Build.0 = Release|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Debug|x64.Build.0 = Debug|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Release|x64.ActiveCfg = Release|Any CPU + {AFCA9D1D-26A6-482A-A5AB-0827AD0FD677}.Signed Release|x64.Build.0 = Release|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Debug|x64.ActiveCfg = Debug|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Debug|x64.Build.0 = Debug|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Release|Any CPU.ActiveCfg = Release|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Release|Any CPU.Build.0 = Release|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Release|x64.ActiveCfg = Release|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Release|x64.Build.0 = Release|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Debug|x64.Build.0 = Debug|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Release|x64.ActiveCfg = Release|Any CPU + {E82D72A1-90F6-4341-A82D-D6B40349DF63}.Signed Release|x64.Build.0 = Release|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Debug|x64.ActiveCfg = Debug|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Debug|x64.Build.0 = Debug|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Release|Any CPU.ActiveCfg = Release|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Release|Any CPU.Build.0 = Release|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Release|x64.ActiveCfg = Release|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Release|x64.Build.0 = Release|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Debug|x64.Build.0 = Debug|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Release|x64.ActiveCfg = Release|Any CPU + {FCB61E3F-2624-4146-BB83-9D2B539D99F9}.Signed Release|x64.Build.0 = Release|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Debug|x64.ActiveCfg = Debug|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Debug|x64.Build.0 = Debug|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Release|Any CPU.ActiveCfg = Release|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Release|Any CPU.Build.0 = Release|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Release|x64.ActiveCfg = Release|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Release|x64.Build.0 = Release|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Debug|x64.Build.0 = Debug|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Release|x64.ActiveCfg = Release|Any CPU + {B597948E-4470-4F98-B018-9BF66244DE76}.Signed Release|x64.Build.0 = Release|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Debug|x64.ActiveCfg = Debug|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Debug|x64.Build.0 = Debug|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Release|Any CPU.ActiveCfg = Release|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Release|Any CPU.Build.0 = Release|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Release|x64.ActiveCfg = Release|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Release|x64.Build.0 = Release|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Debug|x64.Build.0 = Debug|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Release|x64.ActiveCfg = Release|Any CPU + {995F4711-32F9-45CD-BA32-48E638DB479C}.Signed Release|x64.Build.0 = Release|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Debug|x64.ActiveCfg = Debug|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Debug|x64.Build.0 = Debug|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Release|Any CPU.ActiveCfg = Release|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Release|Any CPU.Build.0 = Release|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Release|x64.ActiveCfg = Release|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Release|x64.Build.0 = Release|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Debug|x64.Build.0 = Debug|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Release|x64.ActiveCfg = Release|Any CPU + {BAA2850C-0A9A-4343-9C6C-14840E216A1F}.Signed Release|x64.Build.0 = Release|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Debug|x64.ActiveCfg = Debug|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Debug|x64.Build.0 = Debug|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Release|Any CPU.Build.0 = Release|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Release|x64.ActiveCfg = Release|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Release|x64.Build.0 = Release|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Debug|x64.Build.0 = Debug|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Release|x64.ActiveCfg = Release|Any CPU + {F8CAAED2-0A64-4756-AA97-C0BDD56F2F25}.Signed Release|x64.Build.0 = Release|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Debug|x64.ActiveCfg = Debug|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Debug|x64.Build.0 = Debug|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Release|Any CPU.ActiveCfg = Release|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Release|Any CPU.Build.0 = Release|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Release|x64.ActiveCfg = Release|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Release|x64.Build.0 = Release|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Debug|x64.Build.0 = Debug|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Release|x64.ActiveCfg = Release|Any CPU + {E42AC7B6-8120-40B5-8CD3-C4139B940897}.Signed Release|x64.Build.0 = Release|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Debug|x64.ActiveCfg = Debug|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Debug|x64.Build.0 = Debug|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Release|Any CPU.ActiveCfg = Release|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Release|Any CPU.Build.0 = Release|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Release|x64.ActiveCfg = Release|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Release|x64.Build.0 = Release|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Debug|x64.Build.0 = Debug|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C24EF2AC-49D3-4542-BC40-5D62E12C7DED}.Signed Release|x64.Build.0 = Release|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Debug|x64.ActiveCfg = Debug|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Debug|x64.Build.0 = Debug|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Release|Any CPU.ActiveCfg = Release|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Release|Any CPU.Build.0 = Release|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Release|x64.ActiveCfg = Release|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Release|x64.Build.0 = Release|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Debug|x64.Build.0 = Debug|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Release|x64.ActiveCfg = Release|Any CPU + {31EC737E-E2A9-4FFD-A62B-94C0E4546DBA}.Signed Release|x64.Build.0 = Release|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Debug|x64.ActiveCfg = Debug|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Debug|x64.Build.0 = Debug|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Release|Any CPU.ActiveCfg = Release|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Release|Any CPU.Build.0 = Release|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Release|x64.ActiveCfg = Release|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Release|x64.Build.0 = Release|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Signed Debug|x64.Build.0 = Debug|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {B3E047F9-7648-4969-842B-405701FB274A}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Signed Release|x64.ActiveCfg = Release|Any CPU + {B3E047F9-7648-4969-842B-405701FB274A}.Signed Release|x64.Build.0 = Release|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Debug|Any CPU.Build.0 = Debug|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Debug|x64.ActiveCfg = Debug|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Debug|x64.Build.0 = Debug|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Release|Any CPU.ActiveCfg = Release|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Release|Any CPU.Build.0 = Release|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Release|x64.ActiveCfg = Release|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Release|x64.Build.0 = Release|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Debug|x64.Build.0 = Debug|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Release|x64.ActiveCfg = Release|Any CPU + {863F112D-A4A4-4225-B6DA-4E9BD0625001}.Signed Release|x64.Build.0 = Release|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Debug|x64.Build.0 = Debug|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Release|Any CPU.Build.0 = Release|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Release|x64.ActiveCfg = Release|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Release|x64.Build.0 = Release|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Debug|x64.Build.0 = Debug|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Release|x64.ActiveCfg = Release|Any CPU + {BE62B112-0032-4631-B021-A1008B2CB367}.Signed Release|x64.Build.0 = Release|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Debug|x64.ActiveCfg = Debug|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Debug|x64.Build.0 = Debug|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Release|Any CPU.Build.0 = Release|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Release|x64.ActiveCfg = Release|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Release|x64.Build.0 = Release|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Debug|x64.Build.0 = Debug|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Release|x64.ActiveCfg = Release|Any CPU + {A73B97DD-F870-48D0-86AE-713457B47E2B}.Signed Release|x64.Build.0 = Release|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Debug|x64.ActiveCfg = Debug|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Debug|x64.Build.0 = Debug|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Release|Any CPU.ActiveCfg = Release|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Release|Any CPU.Build.0 = Release|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Release|x64.ActiveCfg = Release|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Release|x64.Build.0 = Release|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Debug|x64.Build.0 = Debug|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Release|x64.ActiveCfg = Release|Any CPU + {868226D4-BC8B-4B91-BD09-8F63D3C9DEBE}.Signed Release|x64.Build.0 = Release|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Debug|x64.ActiveCfg = Debug|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Debug|x64.Build.0 = Debug|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Release|Any CPU.ActiveCfg = Release|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Release|Any CPU.Build.0 = Release|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Release|x64.ActiveCfg = Release|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Release|x64.Build.0 = Release|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Debug|x64.Build.0 = Debug|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Release|x64.ActiveCfg = Release|Any CPU + {9B694CCC-0A7A-4190-AB86-29A20625DD95}.Signed Release|x64.Build.0 = Release|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Debug|x64.ActiveCfg = Debug|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Debug|x64.Build.0 = Debug|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Release|Any CPU.ActiveCfg = Release|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Release|Any CPU.Build.0 = Release|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Release|x64.ActiveCfg = Release|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Release|x64.Build.0 = Release|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Debug|x64.Build.0 = Debug|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Release|x64.ActiveCfg = Release|Any CPU + {A91742F8-923C-4B8C-8E53-C2EC34B80130}.Signed Release|x64.Build.0 = Release|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Debug|x64.ActiveCfg = Debug|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Debug|x64.Build.0 = Debug|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Release|Any CPU.ActiveCfg = Release|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Release|Any CPU.Build.0 = Release|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Release|x64.ActiveCfg = Release|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Release|x64.Build.0 = Release|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Debug|x64.Build.0 = Debug|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Release|x64.ActiveCfg = Release|Any CPU + {EAC542FC-085F-454E-AAED-36B6ECB0A2F8}.Signed Release|x64.Build.0 = Release|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Debug|x64.ActiveCfg = Debug|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Debug|x64.Build.0 = Debug|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Release|Any CPU.ActiveCfg = Release|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Release|Any CPU.Build.0 = Release|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Release|x64.ActiveCfg = Release|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Release|x64.Build.0 = Release|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Debug|x64.Build.0 = Debug|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C9FA4B20-4325-460B-8FDF-8AC577090473}.Signed Release|x64.Build.0 = Release|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Debug|x64.ActiveCfg = Debug|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Debug|x64.Build.0 = Debug|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Release|Any CPU.ActiveCfg = Release|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Release|Any CPU.Build.0 = Release|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Release|x64.ActiveCfg = Release|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Release|x64.Build.0 = Release|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Debug|x64.Build.0 = Debug|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Release|x64.ActiveCfg = Release|Any CPU + {235646F1-1F85-47C9-8BD2-A3E854AC38EB}.Signed Release|x64.Build.0 = Release|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Debug|x64.ActiveCfg = Debug|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Debug|x64.Build.0 = Debug|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Release|Any CPU.ActiveCfg = Release|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Release|Any CPU.Build.0 = Release|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Release|x64.ActiveCfg = Release|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Release|x64.Build.0 = Release|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Debug|x64.Build.0 = Debug|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C862599C-ED16-4D39-80AF-4F71F41302C0}.Signed Release|x64.Build.0 = Release|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Debug|x64.ActiveCfg = Debug|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Debug|x64.Build.0 = Debug|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Release|Any CPU.Build.0 = Release|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Release|x64.ActiveCfg = Release|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Release|x64.Build.0 = Release|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Debug|x64.Build.0 = Debug|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Release|x64.ActiveCfg = Release|Any CPU + {9A62C452-44E3-4263-A91D-8B480259270D}.Signed Release|x64.Build.0 = Release|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Debug|x64.ActiveCfg = Debug|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Debug|x64.Build.0 = Debug|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Release|Any CPU.Build.0 = Release|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Release|x64.ActiveCfg = Release|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Release|x64.Build.0 = Release|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Debug|x64.Build.0 = Debug|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Release|x64.ActiveCfg = Release|Any CPU + {CB2E194B-7C25-4952-BB51-BCAD34E8F406}.Signed Release|x64.Build.0 = Release|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Debug|x64.ActiveCfg = Debug|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Debug|x64.Build.0 = Debug|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Release|Any CPU.Build.0 = Release|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Release|x64.ActiveCfg = Release|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Release|x64.Build.0 = Release|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Debug|x64.Build.0 = Debug|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Release|x64.ActiveCfg = Release|Any CPU + {9E9F2CC8-8190-42B2-8D44-CCC28AC4292A}.Signed Release|x64.Build.0 = Release|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Debug|x64.ActiveCfg = Debug|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Debug|x64.Build.0 = Debug|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Release|Any CPU.ActiveCfg = Release|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Release|Any CPU.Build.0 = Release|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Release|x64.ActiveCfg = Release|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Release|x64.Build.0 = Release|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Debug|x64.Build.0 = Debug|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Release|x64.ActiveCfg = Release|Any CPU + {25183C1B-5A1D-4535-AE62-90105C00BEAF}.Signed Release|x64.Build.0 = Release|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Debug|x64.Build.0 = Debug|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Release|Any CPU.Build.0 = Release|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Release|x64.ActiveCfg = Release|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Release|x64.Build.0 = Release|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Debug|x64.Build.0 = Debug|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Release|x64.ActiveCfg = Release|Any CPU + {CE4F8D70-E17A-4C51-9C9E-BFB42978B5E8}.Signed Release|x64.Build.0 = Release|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Debug|x64.Build.0 = Debug|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Release|Any CPU.ActiveCfg = Release|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Release|Any CPU.Build.0 = Release|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Release|x64.ActiveCfg = Release|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Release|x64.Build.0 = Release|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Debug|x64.Build.0 = Debug|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Release|x64.ActiveCfg = Release|Any CPU + {AFF77CC1-3907-4AD0-B072-B838DB793280}.Signed Release|x64.Build.0 = Release|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Debug|x64.ActiveCfg = Debug|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Debug|x64.Build.0 = Debug|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Release|Any CPU.Build.0 = Release|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Release|x64.ActiveCfg = Release|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Release|x64.Build.0 = Release|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Debug|x64.Build.0 = Debug|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Release|x64.ActiveCfg = Release|Any CPU + {A44583A6-D3DD-4798-A82F-93F54EF1431D}.Signed Release|x64.Build.0 = Release|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Debug|x64.Build.0 = Debug|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Release|Any CPU.Build.0 = Release|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Release|x64.ActiveCfg = Release|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Release|x64.Build.0 = Release|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Debug|x64.Build.0 = Debug|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Release|x64.ActiveCfg = Release|Any CPU + {CE312AFB-2FB6-4436-89D6-33242D26E2A3}.Signed Release|x64.Build.0 = Release|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Debug|x64.ActiveCfg = Debug|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Debug|x64.Build.0 = Debug|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Release|Any CPU.ActiveCfg = Release|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Release|Any CPU.Build.0 = Release|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Release|x64.ActiveCfg = Release|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Release|x64.Build.0 = Release|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Debug|x64.Build.0 = Debug|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Release|x64.ActiveCfg = Release|Any CPU + {185E5F57-2CB6-49B1-B47C-FD6F55EB2E56}.Signed Release|x64.Build.0 = Release|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Debug|x64.ActiveCfg = Debug|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Debug|x64.Build.0 = Debug|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Release|Any CPU.ActiveCfg = Release|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Release|Any CPU.Build.0 = Release|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Release|x64.ActiveCfg = Release|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Release|x64.Build.0 = Release|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Debug|x64.Build.0 = Debug|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C31C5E02-2BCD-4908-B941-B723B758E875}.Signed Release|x64.Build.0 = Release|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Debug|x64.ActiveCfg = Debug|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Debug|x64.Build.0 = Debug|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Release|Any CPU.ActiveCfg = Release|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Release|Any CPU.Build.0 = Release|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Release|x64.ActiveCfg = Release|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Release|x64.Build.0 = Release|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Debug|x64.Build.0 = Debug|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Release|x64.ActiveCfg = Release|Any CPU + {3264F836-203E-4685-BC29-1B41BA386A12}.Signed Release|x64.Build.0 = Release|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Debug|x64.ActiveCfg = Debug|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Debug|x64.Build.0 = Debug|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Release|Any CPU.Build.0 = Release|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Release|x64.ActiveCfg = Release|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Release|x64.Build.0 = Release|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Debug|x64.Build.0 = Debug|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C87ABC52-01D9-4D37-8705-BA0795C7BAEB}.Signed Release|x64.Build.0 = Release|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Debug|x64.Build.0 = Debug|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Release|Any CPU.Build.0 = Release|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Release|x64.ActiveCfg = Release|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Release|x64.Build.0 = Release|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Debug|x64.Build.0 = Debug|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Release|x64.ActiveCfg = Release|Any CPU + {1F67AE40-F8B5-4FD0-9560-ACF1EA6434B4}.Signed Release|x64.Build.0 = Release|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Debug|x64.ActiveCfg = Debug|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Debug|x64.Build.0 = Debug|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Release|Any CPU.ActiveCfg = Release|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Release|Any CPU.Build.0 = Release|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Release|x64.ActiveCfg = Release|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Release|x64.Build.0 = Release|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Debug|x64.Build.0 = Debug|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Release|x64.ActiveCfg = Release|Any CPU + {9ACD49E1-4EE2-4CB0-832F-514D7E475693}.Signed Release|x64.Build.0 = Release|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Debug|x64.ActiveCfg = Debug|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Debug|x64.Build.0 = Debug|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Release|Any CPU.ActiveCfg = Release|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Release|Any CPU.Build.0 = Release|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Release|x64.ActiveCfg = Release|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Release|x64.Build.0 = Release|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Debug|x64.Build.0 = Debug|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Release|x64.ActiveCfg = Release|Any CPU + {09761C44-D1F2-4DB7-B33C-FCDBF260388C}.Signed Release|x64.Build.0 = Release|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Debug|x64.ActiveCfg = Debug|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Debug|x64.Build.0 = Debug|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Release|Any CPU.Build.0 = Release|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Release|x64.ActiveCfg = Release|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Release|x64.Build.0 = Release|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Debug|x64.Build.0 = Debug|Any CPU {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Release|x64.ActiveCfg = Release|Any CPU + {F92D2D61-0DD1-4F73-AAB4-92DCC58F45D0}.Signed Release|x64.Build.0 = Release|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Debug|x64.ActiveCfg = Debug|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Debug|x64.Build.0 = Debug|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Release|Any CPU.Build.0 = Release|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Release|x64.ActiveCfg = Release|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Release|x64.Build.0 = Release|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Debug|x64.Build.0 = Debug|Any CPU {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Release|x64.ActiveCfg = Release|Any CPU + {E65CAF57-DC83-4EA4-A35C-44D259054DB4}.Signed Release|x64.Build.0 = Release|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Debug|x64.ActiveCfg = Debug|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Debug|x64.Build.0 = Debug|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Release|Any CPU.ActiveCfg = Release|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Release|Any CPU.Build.0 = Release|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Release|x64.ActiveCfg = Release|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Release|x64.Build.0 = Release|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Debug|x64.Build.0 = Debug|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Release|x64.ActiveCfg = Release|Any CPU + {C25C9F9F-2874-403F-9AB8-07ED7B1C65AC}.Signed Release|x64.Build.0 = Release|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Debug|x64.ActiveCfg = Debug|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Debug|x64.Build.0 = Debug|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Release|Any CPU.Build.0 = Release|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Release|x64.ActiveCfg = Release|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Release|x64.Build.0 = Release|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Debug|x64.Build.0 = Debug|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Release|x64.ActiveCfg = Release|Any CPU + {38A5EF80-6411-4522-9810-F1BF2FCBC8CB}.Signed Release|x64.Build.0 = Release|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Debug|x64.Build.0 = Debug|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Release|Any CPU.Build.0 = Release|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Release|x64.ActiveCfg = Release|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Release|x64.Build.0 = Release|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Debug|x64.Build.0 = Debug|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Release|x64.ActiveCfg = Release|Any CPU + {CA44F2B7-551E-43B2-8C95-00102FEED9A7}.Signed Release|x64.Build.0 = Release|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Debug|x64.ActiveCfg = Debug|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Debug|x64.Build.0 = Debug|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Release|Any CPU.ActiveCfg = Release|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Release|Any CPU.Build.0 = Release|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Release|x64.ActiveCfg = Release|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Release|x64.Build.0 = Release|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Debug|x64.Build.0 = Debug|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Release|x64.ActiveCfg = Release|Any CPU + {30F7137B-E767-4ED5-AAF9-87729209953E}.Signed Release|x64.Build.0 = Release|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Debug|x64.ActiveCfg = Debug|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Debug|x64.Build.0 = Debug|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Release|Any CPU.Build.0 = Release|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Release|x64.ActiveCfg = Release|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Release|x64.Build.0 = Release|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Debug|x64.Build.0 = Debug|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Release|x64.ActiveCfg = Release|Any CPU + {5F426E12-0FE2-4240-967C-1CFBC0FC30CF}.Signed Release|x64.Build.0 = Release|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Debug|x64.ActiveCfg = Debug|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Debug|x64.Build.0 = Debug|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Release|Any CPU.Build.0 = Release|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Release|x64.ActiveCfg = Release|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Release|x64.Build.0 = Release|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Debug|x64.Build.0 = Debug|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Release|x64.ActiveCfg = Release|Any CPU + {BB72A145-15F9-48AF-BCED-1A80432D74DD}.Signed Release|x64.Build.0 = Release|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Debug|x64.ActiveCfg = Debug|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Debug|x64.Build.0 = Debug|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Release|Any CPU.Build.0 = Release|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Release|x64.ActiveCfg = Release|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Release|x64.Build.0 = Release|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Debug|x64.Build.0 = Debug|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Release|x64.ActiveCfg = Release|Any CPU + {9F0E0C83-D67B-4F14-837A-822AD00331F3}.Signed Release|x64.Build.0 = Release|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Debug|x64.Build.0 = Debug|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Release|Any CPU.Build.0 = Release|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Release|x64.ActiveCfg = Release|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Release|x64.Build.0 = Release|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Debug|x64.Build.0 = Debug|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Release|x64.ActiveCfg = Release|Any CPU + {4E5045CE-B2EB-4371-B33B-ABA1EEF635FA}.Signed Release|x64.Build.0 = Release|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Debug|x64.Build.0 = Debug|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Release|Any CPU.Build.0 = Release|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Release|x64.ActiveCfg = Release|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Release|x64.Build.0 = Release|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Debug|x64.Build.0 = Debug|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Release|x64.ActiveCfg = Release|Any CPU + {4B59C9B9-39CC-4E5E-BD41-273344F5B1B4}.Signed Release|x64.Build.0 = Release|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Debug|x64.ActiveCfg = Debug|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Debug|x64.Build.0 = Debug|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Release|Any CPU.Build.0 = Release|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Release|x64.ActiveCfg = Release|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Release|x64.Build.0 = Release|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Debug|x64.Build.0 = Debug|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Release|x64.ActiveCfg = Release|Any CPU + {4A418B93-D85D-4089-9961-0ABA1FBF1ABD}.Signed Release|x64.Build.0 = Release|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Debug|x64.ActiveCfg = Debug|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Debug|x64.Build.0 = Debug|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Release|Any CPU.Build.0 = Release|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Release|x64.ActiveCfg = Release|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Release|x64.Build.0 = Release|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Debug|x64.Build.0 = Debug|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Release|x64.ActiveCfg = Release|Any CPU + {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0}.Signed Release|x64.Build.0 = Release|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Debug|x64.ActiveCfg = Debug|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Debug|x64.Build.0 = Debug|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Release|Any CPU.ActiveCfg = Release|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Release|Any CPU.Build.0 = Release|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Release|x64.ActiveCfg = Release|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Release|x64.Build.0 = Release|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Debug|x64.Build.0 = Debug|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Release|x64.ActiveCfg = Release|Any CPU + {4448AD66-FF8A-4AB6-B17C-F401CCC6940D}.Signed Release|x64.Build.0 = Release|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Debug|x64.Build.0 = Debug|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Release|Any CPU.Build.0 = Release|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Release|x64.ActiveCfg = Release|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Release|x64.Build.0 = Release|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Debug|x64.Build.0 = Debug|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Release|Any CPU.Build.0 = Release|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Debug|Any CPU.Build.0 = Debug|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Release|Any CPU.ActiveCfg = Release|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Release|Any CPU.Build.0 = Release|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU - {95428F1D-8232-4360-86F8-727139E03426}.Signed Release|Any CPU.Build.0 = Release|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Release|Any CPU.Build.0 = Release|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU - {7C5A3F03-57A3-4009-928A-6C0E1085FA09}.Signed Release|Any CPU.Build.0 = Release|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Release|Any CPU.Build.0 = Release|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Release|x64.ActiveCfg = Release|Any CPU + {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2}.Signed Release|x64.Build.0 = Release|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Debug|x64.ActiveCfg = Debug|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Debug|x64.Build.0 = Debug|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Release|Any CPU.Build.0 = Release|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Release|x64.ActiveCfg = Release|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Release|x64.Build.0 = Release|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Debug|x64.ActiveCfg = Debug|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Debug|x64.Build.0 = Debug|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Release|x64.ActiveCfg = Release|x64 + {4E7B28C0-1A88-4706-B75A-C2733C3CB7E3}.Signed Release|x64.Build.0 = Release|x64 + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Debug|x64.ActiveCfg = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Debug|x64.Build.0 = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Release|Any CPU.Build.0 = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Release|x64.ActiveCfg = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Release|x64.Build.0 = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Debug|x64.Build.0 = Debug|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Release|x64.ActiveCfg = Release|Any CPU + {502C1461-6DE2-4613-BBDB-96EDDFAC73E7}.Signed Release|x64.Build.0 = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Debug|x64.ActiveCfg = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Debug|x64.Build.0 = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Release|Any CPU.Build.0 = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Release|x64.ActiveCfg = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Release|x64.Build.0 = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Debug|x64.ActiveCfg = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Debug|x64.Build.0 = Debug|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Release|x64.ActiveCfg = Release|Any CPU + {90CF2658-A5FE-4695-ABFC-FB10DD445379}.Signed Release|x64.Build.0 = Release|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Debug|x64.ActiveCfg = Debug|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Debug|x64.Build.0 = Debug|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Release|Any CPU.Build.0 = Release|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Release|x64.ActiveCfg = Release|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Release|x64.Build.0 = Release|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Debug|Any CPU.ActiveCfg = Debug|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Debug|Any CPU.Build.0 = Debug|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Debug|x64.ActiveCfg = Debug|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Debug|x64.Build.0 = Debug|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Release|Any CPU.ActiveCfg = Release|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Release|Any CPU.Build.0 = Release|Any CPU + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Release|x64.ActiveCfg = Release|x64 + {279B3B52-9CE6-4A65-B359-4894339A870A}.Signed Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -728,9 +1221,6 @@ Global {39542BC9-A18A-4EF2-AC75-B5A7A9079FB0} = {97A8C5A7-2D37-4237-AB1F-FB7D3053B5C0} {4448AD66-FF8A-4AB6-B17C-F401CCC6940D} = {3DCA5BDA-D495-4CD7-8424-3E33572DFF09} {4E94C7E4-3EC6-4F43-9E08-24B6A90FDEF2} = {16A909F8-F86F-4C65-9202-655E088A7D30} - {95428F1D-8232-4360-86F8-727139E03426} = {CBC45433-8478-4D2B-AF5F-29501B9CB6C9} - {7C5A3F03-57A3-4009-928A-6C0E1085FA09} = {6B587373-3C4C-4127-BFD1-DA9A89C0555B} - {CAC60454-9AA3-4FF8-A2D6-E6A9F3A51726} = {6B587373-3C4C-4127-BFD1-DA9A89C0555B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7B6D2737-94B7-470E-B413-D9693622AA4D}