public ResultDelegate <TSearch, TResult> CreateResultDelegate(LinkedList <CompositPropertyVertex> vertices, SearchStrategy <TSearch, TResult> strategy) { var delegateMap = new Dictionary <CompositPropertyVertex, ProxyDelegate <TSearch, TResult> >(); var delegates = new ProxyDelegate <TSearch, TResult> [vertices.Count]; var index = 0; vertices.ForEach( node => { CreateDelegate(node.Value, delegateMap, strategy); delegates[index++] = delegateMap[node.Value]; }); var rootDelegate = new RootProxyDelegate <TSearch, TResult>(delegates, strategy); rootDelegate.BuildExecuteChildrenDelegate(); return(rootDelegate.Execute); }
private static void CreateDelegate(CompositPropertyVertex vertex, Dictionary <CompositPropertyVertex, ProxyDelegate <TSearch, TResult> > delegateMap, SearchStrategy <TSearch, TResult> strategy) { if (vertex.PropertyList.First == null) { throw new NullReferenceException(); } if (delegateMap.ContainsKey(vertex)) { return; } var propertyGetters = new Func <object, object> [vertex.PropertyList.Count]; var parameter = Expression.Parameter(typeof(object), "obj"); var nullConst = Expression.Constant(null); var hasCollection = false; var index = 0; vertex.PropertyList.ForEach( node => { if (typeof(ICollection).IsAssignableFrom(node.Value.PropertyType)) { hasCollection = true; } var resultVariable = Expression.Variable(typeof(object), "result"); var castVariable = Expression.Variable(node.Value.DeclaringType, "value"); var castAs = Expression.TypeAs(parameter, node.Value.DeclaringType); var castAssign = Expression.Assign(castVariable, castAs); var checkNotNull = Expression.NotEqual(castVariable, nullConst); var memberAccess = Expression.Convert(Expression.MakeMemberAccess(castVariable, node.Value), typeof(object)); var conditionalMemberAccess = Expression.Condition(checkNotNull, memberAccess, nullConst); var resultAssign = Expression.Assign(resultVariable, conditionalMemberAccess); var returnTarget = Expression.Label(typeof(object)); var returnLabel = Expression.Label(returnTarget, nullConst); var returnExpr = Expression.Return(returnTarget, resultVariable); var block = Expression.Block(typeof(object), new[] { castVariable, resultVariable }, castAssign, resultAssign, returnExpr, returnLabel); var deleg = Expression.Lambda <Func <object, object> >(block, parameter).Compile(); propertyGetters[index++] = deleg; }); var childDelegates = new ProxyDelegate <TSearch, TResult> [vertex.Children.Count]; delegateMap[vertex] = new ProxyDelegate <TSearch, TResult>(propertyGetters, childDelegates, strategy, hasCollection); index = 0; vertex.Children.ForEach( node => { CreateDelegate(node.Value, delegateMap, strategy); childDelegates[index++] = delegateMap[node.Value]; }); }