2016-06-16 1 views
0

에 GroupJoin 문을 변환 :이 문 사용하여 두 데이터 집합에 가입 내가 외부을 시도하고있어 익스프레션 트리

var destinationList = inners.GroupJoin(outers, inner => inner.JoinField, outer => outer.JoinField, 
    (inner, outerList) => 
     outerList.Select(outer => new DestinationModel { Id = inner.JoinField, AggregationField = outer.DataField }) 
      .DefaultIfEmpty(new DestinationModel { Id = inner.JoinField })).SelectMany(destination => destination).ToList(); 

이 문제없이 제대로 작동을하지만 결국에이 변환해야 데이터 세트와 필드가 변경되도록하는 표현 트리.

내 데이터 모델

는 다음과 같이 :

InnerModel : 공용 클래스 InnerModel { 공공 INT JoinField; public decimal DataField; }

OuterModel : 공용 클래스 OuterModel { 공공 INT JoinField; public decimal DataField; }

DestinationModel : 공용 클래스 DestinationModel { 공공 INT 아이디; public decimal AggregationField; }

이너는 List<InnerModel>

아우터 내가 길을 최대한 활용하기 위해 관리했습니다 List<OuterModel>

입니다,하지만 난 마지막 단계에서 하회하고있다. 이것은 내가 지금까지 가지고있는 것입니다 :

// Declare variables 
var innerParameter = Expression.Parameter(typeof (InnerModel), "inner"); 
var innerSelect = Expression.Lambda<Func<InnerModel, int>>(Expression.Field(innerParameter, "JoinField"), innerParameter); 
var outerParameter = Expression.Parameter(typeof (OuterModel), "outer"); 
var outerListParameter = Expression.Parameter(typeof (IEnumerable<OuterModel>), "outerList"); 
var outerSelect = Expression.Lambda<Func<OuterModel, int>>(Expression.Field(outerParameter, "JoinField"), outerParameter); 
var existingBinding = Expression.MemberInit(Expression.New(typeof (DestinationModel)), Expression.Bind(typeof (DestinationModel).GetField("Id"), Expression.Field(innerParameter, "JoinField"))); 

// Create lambdas 
var selector = Expression.Lambda<Func<OuterModel, DestinationModel>>(existingBinding, outerParameter); 
var selectMethod = typeof (Enumerable).GetMethods().First(x => x.Name == "Select" && x.GetParameters().Length == 2).MakeGenericMethod(typeof(OuterModel), typeof(DestinationModel)); 
var selectCall = Expression.Call(selectMethod, outerListParameter, selector); 

// Create the inner key selector for the GroupJoin method 
var innerKeySelector = Expression.Lambda(selectCall, innerParameter, outerListParameter); 

이 시점까지는 모든 것이 작동합니다. 방법

유형 인수 'Enumerable.GroupJoin (IEnumerable을, IEnumerable을, Func을, Func을, Func을, TResult :

var result = inners.GroupJoin(outers, innerSelect.Compile(), outerSelect.Compile(), (inner, outerList) => outerList.Select(outer => new DestinationModel {Id = inner.JoinField, AggregationField = outer.DataField}).DefaultIfEmpty(new DestinationModel {Id = inner.JoinField})).SelectMany(destination => destination).ToList(); 

내가 컴파일 오류를 얻을 : 나는 원래 문에 innerKeySelector를 연결하려고 할 때 >) '는 사용법에서 유추 할 수 없습니다. 형식 인수를 명시 적으로 지정하십시오.

나는 분명히 뭔가 빠져있는 것을 알고 있지만, 몇 시간 동안이 작업을 한 후에는 볼 수 없습니다. 누군가 올바른 방향으로 나를 가리킬 수 있습니까?

+0

모델 클래스의 이름을'xxxTestModel'로 변경해야한다는 점을 제외하고는 게시 된 코드에 대한 컴파일러 오류가 발생하지 않습니다. –

+0

코드의 클래스 이름을 수정하고 일부 호출을 단순화했지만 여전히 오류가 발생합니다. – MichaelDotKnox

답변

0

내 대답을 찾았습니다. DefaultIfEmpty 호출을 배치하고 Select 호출의 결과를 제공해야했습니다.

var defaultIfEmptyMethod = typeof (Enumerable).GetMethods().First(x => x.Name == "DefaultIfEmpty" && x.GetParameters().Length == 2).MakeGenericMethod(typeof (DestinationTestModel)); 

가 그럼 난 DefaultIfEmpty를 호출하는 람다 식을 만들어 함께 선택 :

var result = inners.GroupJoin(outers, innerSelect.Compile(), outerSelect.Compile(),innerKeySelectorWithDefault.Compile()).SelectMany(destination => destination).ToList(); 
: 저를 활성화

var innerKeySelectorWithDefault = Expression.Lambda<Func<InnerTestModel,IEnumerable<OuterTestModel>,IEnumerable<DestinationTestModel>>>(Expression.Call(defaultIfEmptyMethod, selectCall, nonExistingBinding), innerParameter, outerListParameter); 

최종 메소드를 호출 나는 DefaultIfEmpty 호출에 대한 MethodInfo를 생성

관련 문제