У меня проблемы с отправкой вызова делегату, чей тип еще не закончен во время отправки. Я уточню: я объявил следующий тип делегата:
// 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.
);
}
}
}
* на открытых экземплярах делегатов .
Это было сложно, потому что MyClass не существует, когда я пытаюсь объявить поле directReadAccessors, которое имеет тип DirectReadAccessor [], или когда я запускаю метод InitalizeClass, который снова использует MyClass, который не существует пока (это то, что я создаю). Тем не менее, мне удалось все это сделать, но теперь у меня возникли проблемы с методом DirectRead, поскольку я не знаю, как вызвать делегат, как только он у меня в стеке. Видимо, мне нужно следующее излучение:
ilGenerator.Emit(OpCodes.Callvirt, invokeMInfo);
где invokeMInfo - это метод Invoke в 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 еще не существует. У меня есть TypeBuilder для MyClass и незаконченный тип DirectReadAccessor, который я создал следующим образом:
directReadAccessorType = typeof(DirectReadAccessor<>).MakeGenericType(typeBuilder);
Но если я пытаюсь вызвать GetMethod ("Invoke", ....) для directReadAccessorType, как показано выше, я получаю NotSupportedException, потому что не могу получить метод Invoke для незавершенного типа. Я проверил это предположение, сделав тот же вызов после завершения типа с:
typeBuilder.CreateType();
И действительно, я не получаю исключения в этом случае. Тем не менее, мне нужно иметь возможность получить MethodInfo метода Invoke перед завершением типа, в то время как я излучаю код для InitializeClass.
Странная ситуация: у меня будет делегат, когда он мне понадобится, но я не могу произвести код для его вызова. Кто-нибудь может предложить какую-либо помощь?
Большое спасибо и простите за длинный пост.