Cómo crear un método dynamic de extensión de combinación LINQ

Hubo una biblioteca de métodos dynamics de extensiones LINQ lanzados como muestra con Visual Studio 2008 . Me gustaría extenderlo con un método de unión. El código siguiente falla con una excepción de coincidencia de parámetros en tiempo de ejecución. ¿Dónde está el problema?

public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { if (inner == null) throw new ArgumentNullException("inner"); if (outerSelector == null) throw new ArgumentNullException("outerSelector"); if (innerSelector == null) throw new ArgumentNullException("innerSelector"); if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor"); LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values); LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values); return outer.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Join", new Type[] { outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, innerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda)) ); } 

Lo arreglé yo mismo ahora. Fue un error de colegial al pasar demasiados parámetros a la llamada CreateQuery (…). Pegue el siguiente código en el archivo Dynamic.cs dentro de la clase DynamicQueryable para un método de extensión de unión dinámica. Puede encontrar el origen para el proyecto de ejemplo DynamicQuery en http://code.msdn.microsoft.com/csharpsamples .
Disfrutar.

  public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { if (inner == null) throw new ArgumentNullException("inner"); if (outerSelector == null) throw new ArgumentNullException("outerSelector"); if (innerSelector == null) throw new ArgumentNullException("innerSelector"); if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor"); LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values); LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values); return outer.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Join", new Type[] {outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda))); } //The generic overload. public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { return (IQueryable)Join((IQueryable)outer, (IEnumerable)inner, outerSelector, innerSelector, resultsSelector, values); } 

Puede instalar el paquete nuget de System.Linq.Dynamic.Core – https://github.com/StefH/System.Linq.Dynamic.Core

Esto tiene el método de unión implementado junto con varios otros métodos auxiliares.

Usando esta biblioteca puedes hacer una simple unión de la siguiente manera

myContext.TableA.Join(myContext.TableB,'Id','TableAId','outer',null)

en el selector de resultados outer e inner son palabras clave para acceder al resultado de la unión.

Usar una clave con múltiples propiedades y / o seleccionar un resultado con múltiples propiedades se puede hacer de la siguiente manera

myContext.TableA.Join(myContext.TableB,'new (Id as key1,Code as key2)','new (TableAId as key1,AnotherCol as key2)','new(outer.Id,inner.Desc)',null)

Aquí hay un código de muestra que muestra una combinación en varias columnas. Usando una tabla de datos y datarows necesitas tener acceso siempre a los campos a través del indexador.

  DataTable t1 = new DataTable(); t1.Columns.Add("FundId", typeof(int)); t1.Columns.Add("Date", typeof(DateTime)); t1.Columns.Add("CodeA", typeof(string)); t1.Rows.Add(1, new DateTime(2010, 01, 01), "A1"); t1.Rows.Add(2, new DateTime(2010, 01, 01), "A2"); t1.Rows.Add(3, new DateTime(2010, 01, 01), "A3"); DataTable t2 = new DataTable(); t2.Columns.Add("FundId", typeof(int)); t2.Columns.Add("Date", typeof(DateTime)); t2.Columns.Add("CodeB", typeof(string)); t2.Rows.Add(1, new DateTime(2010, 01, 01), "B1"); t2.Rows.Add(2, new DateTime(2010, 01, 01), "B2"); t2.Rows.Add(3, new DateTime(2010, 01, 01), "B3"); IQueryable outerTable = t1.AsEnumerable().AsQueryable(); IEnumerable innerTable = t2.AsEnumerable(); var query = outerTable.Join ( innerTable, "new(get_Item(0) as FundId, get_Item(1) as Date)", "new(get_Item(0) as FundId, get_Item(1) as Date)", "new(outer.get_Item(0) as FundId, outer.get_Item(2) as CodeA, inner.get_Item(2) as CodeB)" );