2016-12-29 1 views
1

내가제대로 재산

interface IPoint 
{ 
    int X { get; } 
    int Y { get; } 
} 

그것은 거의 작동처럼 간단한 인터페이스에 대한 인터페이스 implementator을 쓰고 있어요,하지만 난 어떤 속성을 구현하려고 할 때 오류를 신체의

서명을받을 방출 메소드 구현의 선언이 일치하지 않습니다.

Emit은 속성이 일치하지 않는다고 생각하는 이유를 모르겠습니다.

private static class InterfaceImplementator<T> where T: class 
{ 
    [SuppressMessage("ReSharper", "StaticMemberInGenericType")] 
    public static Type Value { get; } 
    static InterfaceImplementator() 
    { 
     var interfaceType = typeof(T); 
     if (!interfaceType.IsInterface) 
     { 
      throw new ArgumentException($"{interfaceType.FullName} should be an interface!"); 
     } 
     var interfaceProps = interfaceType.GetProperties(); 
     if (interfaceType.GetMethods().Except(interfaceProps.Select(x => x.GetMethod).Concat(interfaceProps.Select(x => x.SetMethod))).Any()) 
     { 
      throw new ArgumentException($"{interfaceType.FullName} must have properties only!"); 
     } 
     var tb = Builder.DefineType($"<{interfaceType.Name}>__Implementation", TypeAttributes.Class | TypeAttributes.Sealed); 
     foreach (var interfaceProp in interfaceProps) 
     { 
      var prop = tb.EmitAutoProperty(interfaceProp.Name, interfaceProp.PropertyType); 
      if (interfaceProp.CanRead) 
      { 
       tb.DefineMethodOverride(prop.GetMethod, interfaceProp.GetMethod); 
      } 
      if (interfaceProp.CanWrite) 
      { 
       tb.DefineMethodOverride(prop.SetMethod, interfaceProp.SetMethod); 
      } 
     } 
     tb.AddInterfaceImplementation(interfaceType); 
     Value = tb.CreateType(); 
    } 
} 

EmitProperty : 여기

코드 샘플입니다

public static PropertyInfo EmitAutoProperty(this TypeBuilder tb, string propertyName, Type propertyType) 
{ 
    var backingField = tb.DefineField($"<{propertyName}>k__BackingField", propertyType, FieldAttributes.Private); 
    var propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); 

    var getMethod = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig); 
    var getGenerator = getMethod.GetILGenerator(); 
    getGenerator.Emit(OpCodes.Ldarg_0); 
    getGenerator.Emit(OpCodes.Ldfld, backingField); 
    getGenerator.Emit(OpCodes.Ret); 
    propertyBuilder.SetGetMethod(getMethod); 

    var setMethod = tb.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig); 
    var setGenerator = setMethod.GetILGenerator(); 
    setGenerator.Emit(OpCodes.Ldarg_0); 
    setGenerator.Emit(OpCodes.Ldarg_1); 
    setGenerator.Emit(OpCodes.Stfld, backingField); 
    setGenerator.Emit(OpCodes.Ret); 
    propertyBuilder.SetSetMethod(setMethod); 

    return propertyBuilder; 
} 

답변

3

사용해보십시오 4 인수 DefineMethod는 반환 형식/인수를 정의 할 수 있도록 get_ 및 set_ 메소드 호출

var getMethod = tb.DefineMethod("get_" + propertyName, 
            MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,   
            propertyType, 
            Type.EmptyTypes); 


var setMethod = tb.DefineMethod("set_" + propertyName, 
            MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,   
            null, 
            new [] { propertyType }); 
+1

또한 '가상'이어야합니다. 고맙습니다, 문제가 해결되었습니다. Defenitly 대신 방출 코드를 작성하는 5AM에서 자야합니다 :) –