, Если Вы хотите к представлению readme.txt в Вашем репозитории, не проверяя его:
$ svn кошка http://svn.red-bean.com/repos/test/readme.txt
Это - файл README. Необходимо считать это.Подсказка: Если Ваша рабочая копия устарела (или у Вас есть локальные модификации), и Вы хотите видеть, что ГЛАВНЫЙ пересмотр файла в Вашей рабочей копии, svn кошка автоматически выберет ГЛАВНЫЙ пересмотр, когда Вы дадите ему путь:
кошка foo.c
$ Этот файл находится в моей локальной рабочей копии и имеет изменения, которые я внес.$ svn кошка foo.c
Последний пересмотр только что из репозитория!
Оказывается, я сильно усложнял! Барри Келли был прав :
static T CastDelegate<T>(Delegate src)
where T : class
{
return (T)(object)Delegate.CreateDelegate(
typeof(T),
src.Target,
src.Method,
true); // throw on fail
}
Это работает для моих тестовых случаев.
ОК - это может помочь; он генерирует IL для переключения между типами делегатов, если они соответствуют стандартному шаблону. Он добавляет класс приведения только при необходимости (поэтому, если вы переходите от MouseEventArgs
к EventArgs
, в этом нет необходимости, но это необходимо в обратном направлении). Поскольку вы явно работаете с отражением, я не использовал дженерики (что усложнило бы задачу).
Нахальный момент состоит в том, что вместо использования класса capture он делает вид, что метод принадлежит к классу данные, которые я хотел бы захватить, и использует состояние как arg0
. Я не могу решить, делает это это злым или умным, поэтому я выберу «clevil».
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Windows.Forms;
class Program {
static ParameterInfo[] VerifyStandardHandler(Type type) {
if (type == null) throw new ArgumentNullException("type");
if (!typeof(Delegate).IsAssignableFrom(type)) throw new InvalidOperationException();
MethodInfo sig = type.GetMethod("Invoke");
if (sig.ReturnType != typeof(void)) throw new InvalidOperationException();
ParameterInfo[] args = sig.GetParameters();
if (args.Length != 2 || args[0].ParameterType != typeof(object)) throw new InvalidOperationException();
if (!typeof(EventArgs).IsAssignableFrom(args[1].ParameterType)) throw new InvalidOperationException();
return args;
}
static int methodIndex;
static Delegate Wrap(Delegate value, Type type) {
ParameterInfo[] destArgs = VerifyStandardHandler(type);
if (value == null) return null; // trivial
if (value.GetType() == type) return value; // already OK
ParameterInfo[] sourceArgs = VerifyStandardHandler(value.GetType());
string name = "_wrap" + Interlocked.Increment(ref methodIndex);
Type[] paramTypes = new Type[destArgs.Length + 1];
paramTypes[0] = value.GetType();
for (int i = 0; i < destArgs.Length; i++) {
paramTypes[i + 1] = destArgs[i].ParameterType;
}
DynamicMethod dyn = new DynamicMethod(name, null, paramTypes);
MethodInfo invoker = paramTypes[0].GetMethod("Invoke");
ILGenerator il = dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
if (!sourceArgs[1].ParameterType.IsAssignableFrom(destArgs[1].ParameterType)) {
il.Emit(OpCodes.Castclass, sourceArgs[1].ParameterType);
}
il.Emit(OpCodes.Call, invoker);
il.Emit(OpCodes.Ret);
return dyn.CreateDelegate(type, value);
}
static void Main() {
EventHandler handler = delegate(object sender, EventArgs eventArgs) {
Console.WriteLine(eventArgs.GetType().Name);
};
MouseEventHandler wrapper = (MouseEventHandler)Wrap(handler, typeof(MouseEventHandler));
MouseEventArgs ma = new MouseEventArgs(MouseButtons.Left, 1, 1, 1, 1);
wrapper(new object(), ma);
EventHandler backAgain = (EventHandler)Wrap(wrapper, typeof(EventHandler));
backAgain(new object(), ma);
}
}
Очевидно, вам все равно нужно сгенерировать делегата для события, используя обычные методы ( Delegate.