Я пишу «фабрику слабых событий» - код, который преобразует любого Делегата в нового делегата с идентичной подписью, но с реализацией WeakReference на цели.Я использую MSIL, чтобы избежать вызовов Delegate.CreateDelegate (производительность которого оказалась медленной).
Делегаты со слабыми ссылками отлично работают , пока базовый метод ( Метод исходного делегата), был объявлен публичным.Как только частный или анонимный метод используется, бомбы MSIL во время выполнения с MethodAccessException .
Используя скомпилированные деревья выражений, я смог вызвать частные методы, поэтому ондолжна быть возможность динамически испускать MSIL, который вызывает закрытый метод.... так что не так со следующим?
// var target = this.Target
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Callvirt, targetPropGetter);
il.Emit(OpCodes.Stloc, ilTarget);
// if(target != null)
// {
il.Emit(OpCodes.Ldloc, ilTarget);
il.Emit(OpCodes.Brfalse_S, ilIsNullLabel);
// Method( @target, parm1, parm2 ...);
il.Emit(OpCodes.Ldloc, ilTarget); // this = Target
short argIndex = 1;
foreach (var parm in delgParams) // push all other args
il.Emit(OpCodes.Ldarg, argIndex++);
il.Emit(OpCodes.Callvirt, delegat.Method); // <-- Bombs if method is private
il.Emit(OpCodes.Ret);
// }
il.MarkLabel(ilIsNullLabel);
Так в чем же секрет вызова частного участника?Рефлексия может это сделать, деревья выражений могут сделать это ... почему вышеприведенный код не работает?
РЕДАКТИРОВАТЬ: Большое спасибо всем, кто предоставил ответы здесь.Оказывается, что единственным решением, которое последовательно работало в моем контексте, было использование универсальных делегатов (Action) ..., поскольку Action происходит из mscorlib, JIT, кажется, совершенно счастлив позволить it вызывать закрытый метод.попробуйте использовать свой собственный делегат, и JIT будет работать так же, как если бы вы посылали вызов или Callvirt непосредственно на цель.
Любой, кому интересно посмотреть рабочий код, может перейти к codeplex - ответы, приведенные здесь, помогли реализовать возможности WeakDelegate.