为 List<T> 编译构造函数时出现“CLR 检测到无效程序”
“CLR detected an Invalid Program” when compiling a constructor for List<T>
在将无参数构造函数的 lambda 表达式编译到委托中时,我 运行 遇到了一个奇怪的问题。它几乎适用于我尝试过的所有类型。只有 List<> 正在生成“CLR 检测到无效程序”。 Collection<> 或从 List<> 继承的 class 不会出现问题。
/// <summary>
/// Delegate for activating instances of objects.
/// </summary>
/// <param name="args">Arguments of the construtor.</param>
/// <returns>A new instance of the object.</returns>
public delegate Object InstanceActivator(params object[] args);
/// <summary>
/// Compiles an instance activator.
/// </summary>
/// <param name="objectType">Type of the object to be created.</param>
/// <param name="definition">Constructor parameters as string.</param>
/// <returns>An compiled instance activator to be used for activating new instances of the object.</returns>
public static InstanceActivator CompileDefaultConstructorToInstanceActivator(Type objectType)
{
ConstructorInfo foundConstructor = default(ConstructorInfo);
foreach (ConstructorInfo constructorInfo in objectType.GetTypeInfo().DeclaredConstructors)
{
if(constructorInfo.GetParameters().Length == 0)
{
foundConstructor = constructorInfo;
}
}
ParameterInfo[] paramsInfo = foundConstructor.GetParameters();
ParameterExpression parameter = Expression.Parameter(typeof(object[]), "args");
Expression[] argumentExpressions = new Expression[paramsInfo.Length];
NewExpression newExpression = Expression.New(foundConstructor, argumentExpressions);
LambdaExpression lambda = Expression.Lambda(typeof(InstanceActivator), newExpression, parameter);
return (InstanceActivator)lambda.Compile();
}
因此,当我按以下方式调用此方法时,效果很好:
[TestMethod]
public void CreateGenericCollectionOfString()
{
Object activatedObject = Sandbox.Functions.Activator.CompileDefaultConstructorToInstanceActivator(typeof(Collection<String>))();
Assert.IsNotNull(activatedObject);
Assert.IsInstanceOfType(activatedObject, typeof(Collection<String>));
}
但是下面的测试会抛出一个错误:
[TestMethod]
public void CreateGenericListOfString()
{
Object activatedObject = Sandbox.Functions.Activator.CompileDefaultConstructorToInstanceActivator(typeof(List<String>))();
Assert.IsNotNull(activatedObject);
Assert.IsInstanceOfType(activatedObject, typeof(List<String>));
}
希望有人能给我解释一下原因。
我已将包含重现问题的单元测试的示例项目上传到 GitHub。
https://github.com/teoturner/Sandbox/blob/master/Code/Functions/Activator.cs
https://github.com/teoturner/Sandbox/blob/master/Code/Tests/ActivatorTests.cs
DeclaredConstructors
属性 将 return 甚至是 List<>
的静态构造函数。你显然不能调用它。
使用:
ConstructorInfo foundConstructor = objectType.GetTypeInfo().GetConstructor(Type.EmptyTypes);
在将无参数构造函数的 lambda 表达式编译到委托中时,我 运行 遇到了一个奇怪的问题。它几乎适用于我尝试过的所有类型。只有 List<> 正在生成“CLR 检测到无效程序”。 Collection<> 或从 List<> 继承的 class 不会出现问题。
/// <summary>
/// Delegate for activating instances of objects.
/// </summary>
/// <param name="args">Arguments of the construtor.</param>
/// <returns>A new instance of the object.</returns>
public delegate Object InstanceActivator(params object[] args);
/// <summary>
/// Compiles an instance activator.
/// </summary>
/// <param name="objectType">Type of the object to be created.</param>
/// <param name="definition">Constructor parameters as string.</param>
/// <returns>An compiled instance activator to be used for activating new instances of the object.</returns>
public static InstanceActivator CompileDefaultConstructorToInstanceActivator(Type objectType)
{
ConstructorInfo foundConstructor = default(ConstructorInfo);
foreach (ConstructorInfo constructorInfo in objectType.GetTypeInfo().DeclaredConstructors)
{
if(constructorInfo.GetParameters().Length == 0)
{
foundConstructor = constructorInfo;
}
}
ParameterInfo[] paramsInfo = foundConstructor.GetParameters();
ParameterExpression parameter = Expression.Parameter(typeof(object[]), "args");
Expression[] argumentExpressions = new Expression[paramsInfo.Length];
NewExpression newExpression = Expression.New(foundConstructor, argumentExpressions);
LambdaExpression lambda = Expression.Lambda(typeof(InstanceActivator), newExpression, parameter);
return (InstanceActivator)lambda.Compile();
}
因此,当我按以下方式调用此方法时,效果很好:
[TestMethod]
public void CreateGenericCollectionOfString()
{
Object activatedObject = Sandbox.Functions.Activator.CompileDefaultConstructorToInstanceActivator(typeof(Collection<String>))();
Assert.IsNotNull(activatedObject);
Assert.IsInstanceOfType(activatedObject, typeof(Collection<String>));
}
但是下面的测试会抛出一个错误:
[TestMethod]
public void CreateGenericListOfString()
{
Object activatedObject = Sandbox.Functions.Activator.CompileDefaultConstructorToInstanceActivator(typeof(List<String>))();
Assert.IsNotNull(activatedObject);
Assert.IsInstanceOfType(activatedObject, typeof(List<String>));
}
希望有人能给我解释一下原因。
我已将包含重现问题的单元测试的示例项目上传到 GitHub。
https://github.com/teoturner/Sandbox/blob/master/Code/Functions/Activator.cs https://github.com/teoturner/Sandbox/blob/master/Code/Tests/ActivatorTests.cs
DeclaredConstructors
属性 将 return 甚至是 List<>
的静态构造函数。你显然不能调用它。
使用:
ConstructorInfo foundConstructor = objectType.GetTypeInfo().GetConstructor(Type.EmptyTypes);