我正在使用db4o项目中的System.Linq.Expressions
实现。该代码在.Net Compact Framework 3.5上的Windows Mobile 6上运行。提到here,来源是here。我已经使用了一段时间,而且它运行得非常好。但是,当我尝试将返回引用类型的InvalidCastException
委托转换为表达式树时,我现在遇到Func
。 InvalidCastException
是由我认为是.Net Compact Framework中的错误引起的。我还有第二个代码示例,详细说明了这个错误。
使用System.Linq.Expressions的InvalidCastException示例
using System;
using System.Linq.Expressions;
class Program
{
static void Main(string[] args)
{
// throws InvalidCastException
Expression<Func<object>> expr = () => new object();
}
}
此异常阻止我编写LINQ to SQL,例如Select投射到匿名类型的SQL。
这是异常的完整堆栈跟踪,因为您可以看到其中没有其他信息:
System.InvalidCastException was unhandled
Message="InvalidCastException"
StackTrace:
at ConsoleTest.Program.Main(String[] args)
我使用ILDASM查看了生成的CIL(见下文),结果表明无效的强制转换是从MethodBase
到ConstructorInfo
的强制转换。此强制转换是必要的,因为通过使用NewExpression
类型的参数调用Expression.New
的{{3}},在lambda的主体中生成ConstructorInfo
。对于值类型不会发生这种情况的原因是因为使用了one of the overloads,其中使用了Type
类型的单个参数。 (从我的应用程序中的代码调用带有ConstructorInfo
参数的重载之一可以正常工作,只有当表达式树由编译器生成的代码构建时才会出现问题。)
由于问题出现Expression.New
重载且参数类型为ConstructorInfo
,我尝试更改这些方法并让他们接受MethodBase
甚至object
的参数ConstructorInfo
。但这会产生编译错误:
缺少编译器所需的成员 'System.Linq.Expressions.Expression.New'
显然(并且合理地)编译器对方法的签名非常挑剔。
.Net Compact Framework中的错误示例
以下代码提供了相同的无效转换,但没有使用自定义System.Linq.Expressions
(此代码在.Net 3.5上正常运行但在.Net Compact Framework 3.5上失败):
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
// Get method handle of parameterless constructor
Type type = typeof(object);
ConstructorInfo constructorInfo0 = type.GetConstructor(new Type[0]);
RuntimeMethodHandle runtimeMethodHandle = constructorInfo0.MethodHandle;
// Get method from method handle
MethodBase methodBase =
MethodBase.GetMethodFromHandle(runtimeMethodHandle);
// Casting back to ConstructorInfo throws InvalidCastException on .Net CF
ConstructorInfo constructorInfo1 = (ConstructorInfo)methodBase;
}
}
我的问题(是的,我到了那里,感谢你阅读这篇文章)。
NewExpressions
由New
重载之一创建的ConstructorInfo
参数?InvalidCastException
是.Net Compact Framework中的一个错误,还是该代码尝试执行.Net CF不支持的内容?对于它的价值,这是ILDASM在第一个代码示例中为Main
方法提供的内容:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 40 (0x28)
.maxstack 2
.locals init ([0] class [System.Linq.Expressions]System.Linq.Expressions.Expression`1<class [System.Core]System.Func`1<object>> expr)
IL_0000: nop
IL_0001: ldtoken method instance void [mscorlib]System.Object::.ctor()
IL_0006: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
IL_000b: castclass [mscorlib]System.Reflection.ConstructorInfo
IL_0010: ldc.i4.0
IL_0011: newarr [System.Linq.Expressions]System.Linq.Expressions.Expression
IL_0016: call class [System.Linq.Expressions]System.Linq.Expressions.NewExpression [System.Linq.Expressions]System.Linq.Expressions.Expression::New(class [mscorlib]System.Reflection.ConstructorInfo,
class [System.Linq.Expressions]System.Linq.Expressions.Expression[])
IL_001b: ldc.i4.0
IL_001c: newarr [System.Linq.Expressions]System.Linq.Expressions.ParameterExpression
IL_0021: call class [System.Linq.Expressions]System.Linq.Expressions.Expression`1<!!0> [System.Linq.Expressions]System.Linq.Expressions.Expression::Lambda<class [System.Core]System.Func`1<object>>(class [System.Linq.Expressions]System.Linq.Expressions.Expression,
class [System.Linq.Expressions]System.Linq.Expressions.ParameterExpression[])
IL_0026: stloc.0
IL_0027: ret
} // end of method Program::Main