Я пытаюсь динамически комбинировать любое количество типов с новым типом, который наследует все эти типы. Пока что он должен работать только для интерфейсов.Как создать динамический тип, полученный из закрытого родового типа
Я абсолютно уверен, что есть много подводных камней и сильное влияние на производительность, но это используется только для моего тестового кода - более конкретно, для создания mocks для нескольких интерфейсов.
Таким образом, в основном у меня есть класс (- см. Код ниже), который может создавать эти типы. Это очень хорошо подходит для «простых» типов. Но я хочу иметь возможность передавать и закрытые родовые типы. При попытке этого с моей текущей реализацией возникает TypeLoadException
, когда я пытаюсь создать динамический тип (через TypeBuilder.CreateType
).
Должен ли я указать TypeBuilder
, что новый тип является общим типом, хотя он происходит только из закрытых родовых типов? Если да, как я могу это сделать?
Это, как я использую его:
MultiTypeBuilder multiTypeBuilder =
new MultiTypeBuilder(Guid.NewGuid().ToString());
multiTypeBuilder.SetBaseType(typeof(IFoo));
multiTypeBuilder.SetBaseType(typeof(IBar<IFoo>));
multiTypeBuilder.SetBaseType(typeof(IBaz));
Type multiType = multiTypeBuilder.CreateType();
Это моя текущая реализация (упрощенный немного):
private class MultiTypeBuilder
{
private readonly TypeBuilder m_TypeBuilder;
public MultiTypeBuilder(string name)
{
ModuleBuilder multiTypeModule = GetMultiTypeModule();
TypeAttributes attributes = TypeAttributes.Interface | TypeAttributes.SpecialName | TypeAttributes.Abstract | TypeAttributes.Public;
m_TypeBuilder = multiTypeModule.DefineType(name, attributes);
}
public void SetBaseType(Type baseType)
{
m_TypeBuilder.AddInterfaceImplementation(baseType);
}
public Type CreateType()
{
return m_TypeBuilder.CreateType();
}
private static ModuleBuilder GetMultiTypeModule()
{
AssemblyName assemblyName = new AssemblyName(c_DynamicAssemblyName);
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
return assemblyBuilder.DefineDynamicModule("MultiTypeAssembly");
}
}
Спасибо за вашу поддержку!
В вашем примере IBar определяется так, что T может быть только интерфейсом? Если нет, вы можете попробовать это. –
Fantius
Нет, это не так и не может быть, потому что я не знаю типы во время компиляции. –
Компиляция вашего кода в LINQPad с пустым интерфейсом IBar, IBaz и IFoo работает правильно, не могли бы вы опубликовать какой-то код, который не работает? См. Вывод http://ideone.com/is5gU –