2010-03-03 3 views
3

방출 할 때 유형이 미완료 인 대리인에게 전화를 발신하는 데 문제가 있습니다. 에 *방출 할 때 형식이 완료되지 않은 대리자를 호출하려면 어떻게해야합니까?

public MyClass { 

    // Array of delegates. T has been replaced with MyClass because the 
    // argument will be 'this', which is of type MyClass. 
    private static DirectReadAccessor<MyClass>[] directReadAccessors; 

    // Method that looks up a delegate in the array of delegates and calls it 
    // with 'this'. 
    public Object DirectRead(int i) { 
     directReadAccessors[i](this); 
    } 

    // Method that is called by the declaring type to pass an array with the 
    // MethodInfo of some methods. MyClass then creates delegates for these 
    // methods and stores them in the directReadAccessors array. 
    public static void InitializeClass(MethodInfo[] directReadAccessorsMInfo) { 
     int length = directReadAccessorsMInfo.Length; 
     Type[] typeArguments = new Type[] { typeof(MyClass) }; 
     directReadAccessors = new DirectReadAccessor<MyClass>[length]; 
     // For each method in directReadAccessorsMInfo... 
     for (int i = 0; i < length; i++) { 
      // Create a delegate and store it in directReadAccessors. 
      directReadAccessors[i] = (DirectReadAccessor<MyClass>) 
        Delegate.CreateDelegate(
          DirectReadAccessor<MyClass>, // Type of the delegate. 
          null, // Specify null first argument so that it's 
           // *open* instance. 
          directReadAccessorsMInfo[i].MakeGenericMethod(typeArguments) // The method. 
        ); 
     } 
    } 

} 

: 만든 다음 클래스를

// Delegate type. The 'firstArgument' will be 'this', i.e., this is an open 
// instance method: the implicit argument is here given explicitly, in 
// 'firstArgument'. (See link below for explanation on open instance delegates). 
public delegate Object DirectReadAccessor<T>(T firstArgument); 

그리고 지금의 (a하는 TypeBuilder으로, 즉) 동적에 노력하고있어 : 내가 선언 한 다음 대리자 형식을 : 나는 정교한 것이다 open instance delegates.

DirectReadAccessor [] 유형의 필드 인 directReadAccessors를 선언하려고하거나 MyClass를 다시 사용하는 InitalizeClass 메소드를 내보낼 때 MyClass가 존재하지 않기 때문에 까다로운 작업이었습니다. 아직 존재합니다 (내가 작성한 것입니다). 그러나, 나는이 모든 것을 할 수 있었지만, 이제는 DirectRead 메소드에 문제가있다. 일단 스택에 가지고 있다면 위임자를 호출하는 방법을 모른다. 내가 그렇게 같이 받아야

ilGenerator.Emit(OpCodes.Callvirt, invokeMInfo); 

invokeMInfo이 DirectReadAccessor에서의 메소드 호출이며, 어떤 : : 분명히 내가 필요한 것은 다음과 같은 두 개의 발광입니다

MethodInfo invokeMInfo = typeof(DirectReadAccessor<MyClass>).GetMethod(
     "Invoke",      // Name of the method. 
     BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, // Binding attributes. 
     null,       // Binder. 
     new Type[] { typeof(MyClass) }, // Types of the arguments. 
     null        // Modifiers for the arguments. 
); 

다시, 문제는 그 MyClass의도 DirectReadAccessor도 아직 존재하지 않습니다. 나는 위의 그림과 같이 directReadAccessorType에 (, ...를 "호출")

directReadAccessorType = typeof(DirectReadAccessor<>).MakeGenericType(typeBuilder); 

하지만 getMethod 메소드를 호출하려고하면 : 나는 이렇게 만든 MyClass에와 미완성 DirectReadAccessor 유형의하는 TypeBuilder을 가지고 미완성 된 형식에 대한 메서드 호출을 얻을 수 없기 때문에 NotSupportedException을 가져옵니다. 필자는이 가정을 다음과 같이 유형을 마무리 한 후에 동일한 호출을 수행하여 테스트했습니다.

typeBuilder.CreateType(); 

실제로 예외는 없습니다. 그러나 InitializeClass에 대한 코드를 내보내는 동안 형식을 완료하기 전에 Invoke 메서드의 MethodInfo를 가져올 수 있어야합니다.

이상한 상황입니다. 필요할 때 위임자를 보내 겠지만 위임 코드를 생성 할 수는 없습니다. 아무도 도움을 줄 수 있습니까?

감사합니다. 오랜 기간 동안 죄송합니다.

+0

아니 범죄의 라인을 따라 전화를 사용하여이 MethodInfo 당신이 필요로 얻을 수 TypeBuilder.GetMethod를 사용 할 수 있어야한다고 생각하지만, 그것은 단지 나, 또는 DEVS는 너무 복잡 코드를 작성합니까?! ? –

+0

촬영되지 않았습니다.이 프로젝트는 5 개월짜리 프로젝트로 시작하기에 꽤 복잡한 기존 시스템을 C#으로 이식하려고 시도합니다. 현실에서 내가하려고하는 것은 그다지 복잡하지 않다. 단지 대리자 배열을 가지고 있고, 호출 할 수 있기를 원한다. 유일한 문제는 내가 동적으로 생성 된 유형을 사용하고 있지만 그러한 유형을 사용할 수 없다면 먼저 그 기능을 제공하는 것이 무엇입니까? – Alix

답변

4

그건 까다로운 문제입니다. 난 당신이

TypeBuilder.GetMethod(directReadAccessorType, 
    typeof(DirectReadAccessor<>).GetMethod("Invoke")); 
+0

오 마이 갓, 바로 그거야. 그것은 작동합니다! 너무나 감사합니다. 그래서 너무나 많이, 그렇게 며칠 동안 고생했습니다. (정말 실망스러워서 필요한 라이브러리 호출을 찾는 데 어려움을 겪고 있습니다.) 다시 한 번 감사드립니다, 당신은 정말로 내 하루를 보냈습니다! :) – Alix

+0

@ Alix - 도움이 되었기 때문에 기쁩니다. 불행하게도,'TypeBuilder'에있는 정적 GetMethod, GetField 및 GetConstructor 메소드는 매우 쉽게 발견 할 수 없으므로 Reflection.Emit 및 generics로 복잡한 작업을 할 때 막히게됩니다. – kvb

+0

그것에 대해 이야기 해주세요. :). 저는 C#이 아닌 수년간 프로그래밍을 해오 고 있었고 일반적으로 포럼에서 많은 것을 요구할 필요가 없었습니다.하지만 2 주 전 C#으로 시작한 이래로 저는 꽤 많은 질문을해야했습니다. 허락하신다면, 제가하려고하는 것들 중 일부는 좀 특이합니다 :) – Alix

0

일반 코드를 컴파일하고 ILDASM을 사용하여 보았습니까? 그것은 당신에게 올바른 일리노이와 잘하면 오른쪽을 생성하는 방출을 보여 주어야합니다.

+0

안녕하세요. 그래, 내가 어디에서 "분명히 내가 필요로하는 것은 다음 방출이다"라고 말하면서, 당신이 제안한 것처럼 방출이 얻어졌다. 문제는 내가 델리게이트를 런타임에 스택에로드 할 수 있고 코드를 내보낼 때 delegate의 유형에 특정한 Invoke 메서드를 제공 할 필요없이 (즉, 타입이 잘못 되었기 때문에) 호출하는 것입니다. 아직 존재하지 않는다). – Alix

0

생성 된 클래스의 코드 양을 최소화하는 것이 맞습니까?

이렇게하면 생성 된 클래스가 해당 데이터에 액세스 할 수있는 인터페이스를 구현할 수 있다는 의미입니다. 이를 통해 IL 대신 C#으로 코딩 할 수있는 추가 기능을 구현할 수 있습니다.

+0

안녕하세요. 문제는 이것이 사용자 (이 경우 애플리케이션 프로그래머)가 작성한 클래스를 가져와 일부 기능으로 확장하는 시스템이며 무엇보다도 필드에 대한 액세스가 안전하게 수행된다는 것입니다 (대리인이있는 접근자를 통해 배열 directReadAccessors). 이 모든 작업은 자동으로 수행되어야하며 사용자가 인터페이스를 작성하도록 강요하고 싶지 않습니다. 클래스를 동적으로 내보내서 모든 작업을 수행해야합니다. 이 방법을 더 잘 이해하면 알려주세요. 감사! – Alix

+0

귀하의 요구 사항을 이해할 수 있는지 확실하지 않습니다 (응용 프로그램 프로그래머가 한 가지 방법으로 인터페이스를 구현할 수 있어야합니다). 그러나 문제를 해결할 수있는 또 다른 방법은 C#을 생성하고 csc를 호출 한 다음 컴파일하여 결과를로드하는 것입니다. DLL. 또는 응용 프로그램 프로그래머가이 생성 된 DLL을 참조하도록 빌드 단계 또는 스크립트를 제공하십시오. – Timores

+0

"이것은 사용자가 작성한 클래스를 사용하는 시스템입니다."- * shivers * –

관련 문제