C# 截取具有反射的方法
我试图通过代理类截获一个方法,并得到一个TargetException“Object not match target type”。我相信这类似于PostSharp这样的框架所做的,但我想看看我自己是否可以作为一个练习来做这件事 本例中的目标是使用Diagnostics.Stopwatch将方法调用包装到新的委托中,从而对方法调用计时。不过,这让我有点不知所措 下面是包装代理方法的委托:C# 截取具有反射的方法,c#,reflection,delegates,proxy,closures,C#,Reflection,Delegates,Proxy,Closures,我试图通过代理类截获一个方法,并得到一个TargetException“Object not match target type”。我相信这类似于PostSharp这样的框架所做的,但我想看看我自己是否可以作为一个练习来做这件事 本例中的目标是使用Diagnostics.Stopwatch将方法调用包装到新的委托中,从而对方法调用计时。不过,这让我有点不知所措 下面是包装代理方法的委托: public static Func<Object> Time(this MethodI
public static Func<Object> Time(this MethodInfo target, object parent, object[] parameters, Action<string> logger)
{
return delegate
{
Stopwatch s = new Stopwatch();
s.Start();
object value = target.Invoke(parent, parameters);
s.Stop();
logger("Elapsed ms for function '" + target.Name + "' = " + s.ElapsedMilliseconds.ToString());
return value;
};
}
但是我得到了错误-对象与目标类型不匹配。我检查了MethodInfo实例,DeclaringType是FunctionInterceptor,这意味着我应该如上所述传递拦截器的实例。不知道问题出在哪里
如果我这样做,它工作得很好(只需调用MethodInfo而不包装它):
其中,obj是声明有问题的方法的实例,即用[Time]属性修饰的实例
谢谢 在拦截调用中,您正在创建一个新的MethodInfo对象。MethodInfo对象与您传入的对象完全不同。它不是来自从原始对象类型继承的类(也不是来自FunctionInterceptor类)。如果您改为这样做:
public object Intercept(object proxy, MethodInfo method, object[] args)
{
var data = method.GetCustomAttributes(typeof(TimeAttribute), true);
object result = default(object);
foreach (object d in data)
{
if (d.GetType() == typeof(TimeAttribute)) // [Time] attribute
{
result = method.Time(proxy, args, Log.Write).DynamicInvoke(args);
}
}
return result;
}
它将起作用,因为本例中的方法实际上来自代理的类型。调用Invoke(interceptor,parameters)时,方法本身必须来自FunctionInterceptor类型。在这种情况下,它不是(您可以在那里创建它,但FunctionInterceptor不是新函数的声明类型)。事实上,新函数的声明类型类似于()\u ClassSomethingOrOther。顺便说一句,PostSharp通过在执行之前修改IL并在方法内部注入代码来实现。是的,我也这么认为,类似的结果有不同的方式。
var interceptor = new FunctionInterceptor();
retVal = interceptor.Intercept(proxy, method, parameters).Invoke(interceptor, parameters);
retVal = method.Invoke( obj, parameters );
public object Intercept(object proxy, MethodInfo method, object[] args)
{
var data = method.GetCustomAttributes(typeof(TimeAttribute), true);
object result = default(object);
foreach (object d in data)
{
if (d.GetType() == typeof(TimeAttribute)) // [Time] attribute
{
result = method.Time(proxy, args, Log.Write).DynamicInvoke(args);
}
}
return result;
}