14
此代码段是我的类代码,这创建引用彼此作为参数以一般型两类简化提取物:为什么当发射通过值类型泛型相互引用的类时,我会得到此异常?
namespace Sandbox
{
using System;
using System.Reflection;
using System.Reflection.Emit;
internal class Program
{
private static void Main(string[] args)
{
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule("Test");
var typeOne = module.DefineType("TypeOne", TypeAttributes.Public);
var typeTwo = module.DefineType("TypeTwo", TypeAttributes.Public);
typeOne.DefineField("Two", typeof(TestGeneric<>).MakeGenericType(typeTwo), FieldAttributes.Public);
typeTwo.DefineField("One", typeof(TestGeneric<>).MakeGenericType(typeOne), FieldAttributes.Public);
typeOne.CreateType();
typeTwo.CreateType();
Console.WriteLine("Done");
Console.ReadLine();
}
}
public struct TestGeneric<T>
{
}
}
哪个应当产生MSIL等效于以下语句:
public class TypeOne
{
public Program.TestGeneric<TypeTwo> Two;
}
public class TypeTwo
{
public Program.TestGeneric<TypeOne> One;
}
但不是引发此异常就行typeOne.CreateType()
:
System.TypeLoadException was unhandled
Message=Could not load type 'TypeTwo' from assembly 'Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Source=mscorlib
TypeName=TypeTwo
StackTrace:
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at Sandbox.Program.Main(String[] args) in C:\Users\aca1\Code\Sandbox\Program.cs:line 20
利息注意事项:
- 循环引用不需要引起异常;如果我没有在
TypeTwo
上定义字段One
,则在TypeTwo
之前创建TypeOne
仍然失败,但在TypeOne
成功之前创建TypeTwo
。因此,该异常具体是由于在通用字段类型中使用尚未创建的类型作为参数而引起的;然而,因为我需要使用循环引用,所以我无法通过按特定顺序创建类型来避免这种情况。 - 是的,我做需要使用循环引用。
- 删除包装
TestGeneric<>
类型并声明字段为TypeOne
&TypeTwo
直接不会产生此错误;因此我可以使用已定义但尚未创建的动态类型。 - 将
TestGeneric<>
从struct
更改为class
不会产生此错误;所以这种模式确实与大多数泛型一起工作,只是不是泛型值类型。 - 在我的情况下,我无法更改
TestGeneric<>
的声明,因为它在另一个程序集中声明 - 具体地说,在System.Data.Linq.dll中声明System.Data.Linq.EntityRef<>
。 - 我的循环引用是由表示两个表的外键彼此引用引起的;因此需要特定的通用类型和这种特定的模式。
- 将循环引用更改为自引用编辑成功。原本这是因为我在程序中有
TestGeneric<>
作为嵌套类型,所以它继承了internal
可见性。我已经在上面的代码示例中解决了这个问题,事实上它确实有效。 - 手动编译生成的代码(如C#代码)也可以工作,所以它不是一个模糊的编译器问题。
任何想法a)为什么发生这种情况,b)我如何解决这个问题和/或c)我可以如何解决它?
谢谢。
有趣的;你实际上是在TypeResolver中创建typeTwo,这会导致它在创建的typeOne的中途创建,但是足够迟的时间以至于运行时处理到typeOne存在。这个代码的一个问题是,两种类型必须在创建之前完全定义;在这个例子中,我碰巧正在这样做,但必须确保在我的生产代码中执行该操作。无论如何,这解决了我的问题,所以谢谢! – FacticiusVir
很高兴提供帮助。这是一个特别有趣/有趣的问题。事实上,涉及循环关系的类型必须准备在同一时间点创建。谢谢你指出。 – Scott