Я пытаюсь написать перехватчик на основе атрибутов (что-то похожее на DynamicProxy
). Идея заключается в том, что на основе определенных пользовательских атрибутов будет вызываться метод внутри этого атрибута, т.е.
- Вызов метода внутри класса атрибута до вызова фактического метода.
- Вызов фактического методаmethod.
Я могу переопределить существующий метод, используя MethodBuilder
и TypeBuilder
. Тем не менее, я не могу понять, как вызвать метод внутри атрибута.
Мой код:
static void CreateMethods<T>(TypeBuilder tb)
{
foreach (var methodToOverride in typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
var attribute = (ProxyMethod)methodToOverride.GetCustomAttribute(typeof(ProxyMethod));
if (attribute == null)
continue;
MethodBuilder methodBuilder = tb.DefineMethod(
methodToOverride.Name,
MethodAttributes.Public
| MethodAttributes.HideBySig
| MethodAttributes.NewSlot
| MethodAttributes.Virtual
| MethodAttributes.Final,
CallingConventions.HasThis,
methodToOverride.ReturnType,
Type.EmptyTypes
);
ILGenerator il = methodBuilder.GetILGenerator();
il.Emit(OpCodes.Ldstr, "The I.M implementation of C"); //step1
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //step1
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, methodToOverride);
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(methodBuilder, methodToOverride);
}
}
То, что я должен сделать, это загрузить attribute
в стек, а затемпозвоните attribute.attributeMethod()
, отправив вызов на MethodInfo
. Однако везде, где я смотрю, я могу найти примеры создания нового экземпляра возражения с использованием OpCodes.NewObj
. Я не хочу использовать это, потому что атрибуты могут иметь параметры.
Я не могу думать ни о каком вызове метода внутри класса атрибута (который заменил бы комментарий step1).
РЕДАКТИРОВАТЬ: На основании комментариев я пытаюсь переместить GetCustomAttribute
часть кода в IL. Это то, что у меня сейчас есть
il.Emit(OpCodes.Ldtoken, methodToOverride);
il.Emit(OpCodes.Ldtoken, typeof(ProxyMethod));
il.Emit(OpCodes.Call, typeof(Attribute).GetMethod("GetCustomAttribute", new [] { typeof(MemberInfo), typeof(Type) }));
Это выдает ошибку для меня. Любые советы?