3

我无法向发出时类型未完成的委托发出调用。我会详细说明:我已经声明了以下委托类型:

// 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);

现在我正在尝试动态(即,使用 TypeBuilder)创建以下类:

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.
                    );
        }
    }

}

*在打开的实例委托上。

这很棘手,因为当我尝试声明类型为 DirectReadAccessor [] 的字段 directReadAccessors 时,或者当我发出再次使用 MyClass 的方法 InitalizeClass 时,MyClass 不存在,但它还不存在(即我正在创造什么)。然而,我已经设法做到了这一切,但现在我在使用 DirectRead 方法时遇到了问题,因为一旦我将委托放在堆栈上,我不知道如何调用它。显然我需要的是以下发射:

ilGenerator.Emit(OpCodes.Callvirt, invokeMInfo);

其中 invokeMInfo 是 DirectReadAccessor 上的 Invoke 方法,我应该像这样获取它:

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 都不存在。我有 MyClass 的 TypeBuilder 和未完成的 DirectReadAccessor 类型,我是这样创建的:

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

但是,如果我尝试在 directReadAccessorType 上调用 GetMethod("Invoke", ....),如上所示,我会收到 NotSupportedException,因为我无法为未完成的类型获取方法 Invoke。我已经通过在最终确定类型后进行相同的调用来测试这个假设:

typeBuilder.CreateType();

事实上,在这种情况下我没有得到例外。但是,我需要能够在最终确定类型之前获取 Invoke 方法的 MethodInfo,同时我正在为 InitializeClass 发出代码。

这是一个奇怪的情况:当我需要委托时,我会有委托,但我无法生成调用它的代码。任何人都可以提供任何帮助吗?

非常感谢,很抱歉这篇冗长的帖子。

4

3 回答 3

4

这是一个棘手的问题。我认为你应该能够使用调用TypeBuilder.GetMethod来获得MethodInfo你需要的东西

TypeBuilder.GetMethod(directReadAccessorType, 
    typeof(DirectReadAccessor<>).GetMethod("Invoke"));
于 2010-03-03T20:21:08.340 回答
0

您是否尝试过编译通用代码并使用 ILDASM 查看它?它应该向您展示正确的 IL 并希望生成正确的发射。

于 2010-03-03T09:14:27.890 回答
0

最小化生成类中的代码量是否有意义?

我的意思是,生成的类可以实现一个可以访问其数据的接口。通过它,您可以实现可以用 C# 而不是 IL 编码的附加功能。

于 2010-03-03T11:01:17.160 回答