Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 截取具有反射的方法_C#_Reflection_Delegates_Proxy_Closures - Fatal编程技术网

C# 截取具有反射的方法

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

我试图通过代理类截获一个方法,并得到一个TargetException“Object not match target type”。我相信这类似于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实例,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;
}