2014-12-02 2 views
1

제네릭 부모에서 제네릭 클래스를 만들려고합니다. 하지만 나는 항상 InvalidProgramException을 얻는다.제네릭 기본 유형에서 비 제너릭 유형 출력

내 기본 클래스 :

public interface IServiceType{} 
public class ServiceType: IServiceType{} 
public class EntityType{} 
public class KeyType{} 

public class Base<TService,TEntity, TKey> 
{ 
    public Base(TService service) 
    { 
     Service = service; 
    } 

    public TService Service { get; set; } 
} 

유형 생성자 : ". 호출 대상이 예외를 Throw했습니다"나는 부르고 때

static Type CreateType(Type serviceType, Type entityType, Type keyType) 
{ 
    var assemblyName = new AssemblyName("AssName"); 
    var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
    var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainMod"); 

    var tb = moduleBuilder.DefineType(serviceType.Name.Substring(1)+entityType.Name, TypeAttributes.Public); 

    var baseType = typeof (Base<,,>).MakeGenericType(serviceType, entityType, keyType); 

    tb.SetParent(baseType); 

    var baseCtor = baseType.GetConstructor(new [] {serviceType}); 
    if (baseCtor == null) 
     throw new InvalidOperationException("Base type constuctor not found"); 

    var constuctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] {serviceType}); 

    var ilgen = constuctor.GetILGenerator(); 
    ilgen.Emit(OpCodes.Ldarg_0); 
    ilgen.Emit(OpCodes.Call, baseCtor); 
    ilgen.Emit(OpCodes.Ret); 

    return tb.CreateType(); 
} 

내가 얻고 호출

void Main() 
{ 
    var type = CreateType(typeof(IServiceType), typeof(EntityType), typeof(KeyType)); 
    var instance = Activator.CreateInstance(type, new ServiceType{}); 
    instance.Dump(); 
} 

무엇이 잘못 되었나요?

답변

4

당신은 this을 통과해야하고, 첫 번째 매개 변수

var ilgen = constuctor.GetILGenerator(); 
ilgen.Emit(OpCodes.Ldarg_0); // this 
ilgen.Emit(OpCodes.Ldarg_1); // 1st parameter 
ilgen.Emit(OpCodes.Call, baseCtor); 
ilgen.Emit(OpCodes.Ret); 

Protip : 항상 어셈블리에 생성 된 IL을 덤프하고 PEVerify으로 확인하십시오.

+1

tb.SetParent를 사용하고 DefineType에서 기본 유형을 정의하는 것은 동일한 효과가 있습니다. 제안한 Emit 명령으로 문제가 해결되었습니다. 정말 고마워요. –

+0

죄송합니다. 통지하지 않았습니다. p 일반적인 재귀 유형 정의가있는 경우 가끔 필요합니다. 예'Foo : Something ' – leppie