我試圖通過代理類攔截一個方法,並得到一個TargetException「對象與目標類型不匹配」。我相信這與PostSharp這樣的框架類似,但我想看看我是否可以自己作爲一個練習來做到這一點。用反射截取一個方法
本例中的目標是使用Diagnostics.Stopwatch將方法調用包裝到一個新代理中。儘管如此,它還是讓我有點頭痛。
這裏是一個包裝了代理的方式委託:
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實例的方法該方法是否具有一定的屬性,指示它應定時:
public class FunctionInterceptor
{
public MethodInfo Intercept(Object proxy, MethodInfo method, Object[] args)
{
return new Func<Object>(() =>
{
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;
}).Method; // returning MethodInfo of this delegate
}
現在看來,我應該能夠調用的委託,這MethodInfo對象描述:
var interceptor = new FunctionInterceptor();
retVal = interceptor.Intercept(proxy, method, parameters).Invoke(interceptor, parameters);
但我得到錯誤 - 對象不符合目標類型。我檢查了MethodInfo實例,並且DeclaringType是FunctionInterceptor,這意味着我應該像上面那樣傳入攔截器的實例。不確定是什麼問題。
如果我這樣做,它工作正常(只需調用的MethodInfo不其包裝):
retVal = method.Invoke(obj, parameters);
如果obj是實例聲明有問題的方法中,一個飾以[時間]屬性。
謝謝。
順便說一句,PostSharp通過修改IL並在執行前在方法內部注入代碼來實現它。 –
是的,我認爲很多,類似的結局不同的手段。 –