Этот фрагмент кода представляет собой упрощенный фрагмент моего кода создания классов, который создает два класса, которые ссылаются друг на друга как аргументы в универсальном типе:
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
Интересные вещи, на которые следует обратить внимание:
One
на TypeTwo
, создание TypeOne
до TypeTwo
по-прежнему не удается, но создание TypeTwo
] перед TypeOne
успешно. Следовательно, исключение конкретно вызвано использованием типа, который еще не был создан, в качестве аргумента в универсальном типе поля; однако, поскольку мне нужно использовать циклическую ссылку, я не могу избежать этой ситуации, создавая типы в определенном порядке. TestGeneric <>
и объявление полей как TypeOne
& TypeTwo
напрямую не вызывает эту ошибку; таким образом, я могу использовать динамические типы, которые были определены, но не созданы. TestGeneric <>
с struct
на класс
] не вызывает этой ошибки; так что этот шаблон действительно работает с большинством универсальных типов, но не с универсальными типами значений. TestGeneric <>
в моем случае, поскольку оно объявлено в другом сборка - в частности, System.Data.Linq.EntityRef <>
, объявленная в System.Data.Linq.dll. TestGeneric <>
в качестве вложенного типа в Program, поэтому он унаследовал внутреннюю
видимость. Я исправил это сейчас в примере кода выше, и он действительно работает. Любые идеи по поводу ) почему это происходит, б) как я могу это исправить и / или в) как я могу это решить?
Спасибо.