Hello,
yesterday we have ran into a runtime error in our code that was caused by incorrect compilation of the code that uses combination of LINQ expressions and lambda functions that use parameters from defined method. In the attachment you’ll find code snippet that produces this exact error.
LambdaTestCase.zip (1.3 MB)
In the code snippet you can find method Zkopiruj_pripojene_spisy
in the file _CSpis_kniha_spisu.Impl.pas which contains the problematic code and our way how to fix it temporarily. If you build the provided solution once with problematic code and a second time with the fix and compare these two dll files in e.g. ILSpy or .NetPeek you will see this difference:
public static void Zkopiruj_pripojene_spisy(IOWManager OWManager, OWObject Obj_odkud, OWObject Obj_kam)
{
<>c__DisplayClass0 <>c__DisplayClass = new <>c__DisplayClass0();
<>c__DisplayClass.OWManager = OWManager;
<>c__DisplayClass.source = Obj_odkud;
IConditionableQuery<_ICSpis> conditionableQuery = <>c__DisplayClass.OWManager.Query<_ICSpis>();
ParameterExpression parameterExpression = Expression.Parameter(typeof(_ICSpis), "s");
LabelTarget target = Expression.Label();
ParameterExpression parameterExpression2 = Expression.Variable(typeof(bool), "Result");
ParameterExpression parameterExpression3 = Expression.Variable(typeof(<>c__DisplayClass1), "OX$<>8__locals1");
ParameterExpression parameterExpression4 = Expression.Parameter(typeof(_ICSpis), "ks");
List<long> kolekceSpisuIDOdkud = (from s in conditionableQuery.Where(Expression.Lambda<Func<_ICSpis, bool>>(Expression.Block(new ParameterExpression[1] { parameterExpression2 } as IEnumerable<ParameterExpression>, Expression.Block(new ParameterExpression[1] { parameterExpression3 } as IEnumerable<ParameterExpression>, Expression.Assign(parameterExpression3, Expression.New((ConstructorInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle), new Expression[0])), Expression.Assign(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), Expression.Constant(<>c__DisplayClass, typeof(<>c__DisplayClass0))), Expression.Assign(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), parameterExpression), Expression.Block(Expression.Assign(parameterExpression2, Expression.AndAlso(Expression.GreaterThan(Expression.Property(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), (MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(IOWObject).TypeHandle)), Expression.Constant(0L, typeof(long))), Expression.Call((MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(QueryExtension).TypeHandle), Expression.Call((MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(OWManagerExtensions).TypeHandle), Expression.Field(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass0).TypeHandle))), Expression.Quote(Expression.Lambda<Func<_ICSpis, bool>>(Expression.AndAlso(Expression.Equal(parameterExpression4, Expression.Field(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass0).TypeHandle))), Expression.Equal(Expression.Property(parameterExpression4, (MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(IOWObject).TypeHandle)), Expression.Property(Expression.Field(parameterExpression3, FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/, typeof(<>c__DisplayClass1).TypeHandle)), (MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(IOWObject).TypeHandle)))), new ParameterExpression[1] { parameterExpression4 }))))), Expression.Return(target))), Expression.Label(target), parameterExpression2), new ParameterExpression[1] { parameterExpression }))
select s.ID).ToList();
}
VS.
public static void Zkopiruj_pripojene_spisy(IOWManager OWManager, OWObject Obj_odkud, OWObject Obj_kam)
{
List<long> kolekceSpisuIDOdkud = (from s in OWManager.Query<_ICSpis>()
where s.ID > 0L && OWManager.Query<_ICSpis>().Any((_ICSpis ks) => ks == Obj_odkud && ks.ID == s.ID)
select s.ID).ToList();
}
Our main problem with this is that there is a creation of Block
objects that are not supported in our code. (Rightfully so)
Thanks in advance.