Compact Framework上使用System.Linq.Expressions的InvalidCastException

时间:2014-06-14 19:56:40

标签: c# .net linq compact-framework

我正在使用db4o项目中的System.Linq.Expressions实现。该代码在.Net Compact Framework 3.5上的Windows Mobile 6上运行。提到here,来源是here。我已经使用了一段时间,而且它运行得非常好。但是,当我尝试将返回引用类型的InvalidCastException委托转换为表达式树时,我现在遇到FuncInvalidCastException是由我认为是.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(见下文),结果表明无效的强制转换是从MethodBaseConstructorInfo的强制转换。此强制转换是必要的,因为通过使用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;
    }
}

我的问题(是的,我到了那里,感谢你阅读这篇文章)。

  • 我可以做任何事情来使第一个代码示例工作吗?
  • 更一般地,我可以做任何事情来从编译器中获取表达式树,其中正文具有NewExpressionsNew重载之一创建的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

0 个答案:

没有答案