인터페이스가 이식 가능한 클래스 라이브러리에있을 때 명시 적 인터페이스 속성에서 PEVerify가 실패 함

에릭

get 메서드로 간단한 인터페이스 속성을 명시 적으로 구현하는 클래스를 내 보냅니다. 이식 가능한 클래스 라이브러리에 인터페이스가 정의되어 있지 않으면 문제가 없습니다. 그러나 인터페이스를 PCL로 이동하고 IEnumerable<int>, PEVerify 와 같은 특정 유형 만 사용 하면 PEVerify가 실패합니다.

보면 ILDASM -> 메타 정보는 ->보기 , 당신은 둘 것을 볼 것입니다 mscorlibSystem.Runtime조립 참조를 가져옵니다. 이것은 DefineMethodOverride(볼 수 AssemblyBuilder.GetReferencedAssemblies()있도록)에 전화하는 동안 발생합니다 . IEnumerable`1이 두 어셈블리 모두에서 TypeRef로 가져온 것을 볼 수 있는데, 이는 문제인 것 같습니다.

인터페이스를 PCL로 분리하지 않거나 유형을 다른 것으로 변경하면 작동하며 System.Runtime참조는 포함되지 않습니다. 시도하려면 string교체 IEnumerable<int>string인터페이스뿐만 아니라에서 DefineProperty/ DefineMethod전화.

이 문제를 재현하는 간단한 방법으로 MSDN 의 수정 된 예제 사용하여 콘솔 프로젝트에 아래 코드를 드롭하면 모든 것이 잘 작동합니다. interface I이식 가능한 클래스 라이브러리 프로젝트로 이동 하면 내가 의미하는 바를 정확히 알 수 있습니다.

PEVerify 오류를 어떻게 제거 할 수 있습니까?

오류 : MethodImpl의 Decl (token = 0x0a000001) 및 Body (token = 0x00610072) 메서드 서명이 일치하지 않습니다. [토큰 : 0x19000001] [시간 : 0x801312F4]

public interface I
{
    IEnumerable<int> E { get; }
}

class Test
{
    static void Main()
    {
        string name = "DefineMethodOverrideExample";
        AssemblyName asmName = new AssemblyName(name);
        AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder mb = ab.DefineDynamicModule(name, name + ".dll");
        TypeBuilder tb = mb.DefineType("C", TypeAttributes.Public);
        tb.AddInterfaceImplementation(typeof(I));

        PropertyBuilder prop = tb.DefineProperty("I.E", PropertyAttributes.None, typeof(IEnumerable<int>), Type.EmptyTypes);

        MethodBuilder mbIM = tb.DefineMethod(
            "I.get_E",
            MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName,
            typeof(IEnumerable<int>),
            Type.EmptyTypes);
        prop.SetGetMethod(mbIM);

        ILGenerator il = mbIM.GetILGenerator();
        il.Emit(OpCodes.Ldnull);
        il.Emit(OpCodes.Ret);

        tb.DefineMethodOverride(mbIM, typeof(I).GetProperty("E").GetGetMethod());

        Type tc = tb.CreateType();

        ab.Save(name + ".dll");
    }
}

(.Net 4.5.1)

(C : \ Program Files (x86) \ Microsoft SDKs \ Windows \ v8.1A \ bin \ NETFX 4.5.1 Tools \ x64의 PEVerify 및 ILDASM 버전 4.0.30319.33440)

감사!

에릭

내보내고 컴파일 된 예제와 좀 더 비교하고 .NET 라이브러리 를 파헤친 후 ModuleBuilder.DefineMethodOverrideNoLock-> GetMethodTokenInternalNoLock(인터페이스에서) 에 대한 호출에서 주요 차이점을 발견 할 수있었습니다. 제공은 MethodInfoA는 RuntimeMethodInfo. 궁극적으로를 호출 GetMemberRefOfMethodInfo하면을 포함 System.Runtime하여 IEnumerable.

비공개 멤버에 반영 할 필요가없는 방식으로이 문제를 해결하려면 MethodInfo모든 메서드를 재정의 하는 상속 되는 프록시 또는 래퍼를 만들어 원본 RuntimeMethodInfo. 이렇게하면 ILDASM이 PCL 인터페이스 메서드를 명시 적으로 구현하려는 컴파일 된 (비 방출) 어셈블리에 나타나는 TypeRef 및 TypeSpec 요소를 표시합니다. 이 기술을 사용하여 방출 된 어셈블리를 성공적으로 확인할 수있었습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관