Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.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#_.net_Oop_Generics_Aop - Fatal编程技术网

C# 使用反射截获方法调用或属性更改

C# 使用反射截获方法调用或属性更改,c#,.net,oop,generics,aop,C#,.net,Oop,Generics,Aop,我正在尝试创建一个泛型类,它将在调用方法或访问或更改属性时触发事件。它也可能会触发事件以响应其他更改或正在采取的操作,但目前仅此而已 为了做到这一点,我想拦截每个方法调用和每个属性访问/更改,但我无法确切知道我正在处理哪些方法。没有给定的接口定义我将使用的每个泛型类型T,因此我必须使用反射。下面是我的设想(Trigger是类,而generic将是T类型): 我意识到我把问题过分简化了。首先,我必须处理参数。其次,您不能像那样以编程方式重写一个方法。第三,我还没有开始研究房地产。另外,我必须只更改

我正在尝试创建一个泛型类,它将在调用方法或访问或更改属性时触发事件。它也可能会触发事件以响应其他更改或正在采取的操作,但目前仅此而已

为了做到这一点,我想拦截每个方法调用和每个属性访问/更改,但我无法确切知道我正在处理哪些方法。没有给定的接口定义我将使用的每个泛型类型
T
,因此我必须使用反射。下面是我的设想(
Trigger
是类,而
generic
将是
T
类型):

我意识到我把问题过分简化了。首先,我必须处理参数。其次,您不能像那样以编程方式重写一个方法。第三,我还没有开始研究房地产。另外,我必须只更改对象的这些内容,而不是整个类型,所以我也不确定这是如何工作的

我已经做了研究,发现所有的内容都很混乱。我意识到我应该以某种方式使用AOP,但除了OOP和过程编程之外,我从未做过任何事情,所以我相当迷失在这密集的知识丛林中。听起来我需要使用PostSharp或Unity,但我仍然不知道如何使用after、and、and和(每个单词都有单独的链接)

有没有更简单的方法?我甚至可以在不使用接口或预定义类的情况下完成它吗


是泛型让我的问题变得特别复杂。如果我可以让一个类继承自
T
,然后使用代理来捕获它的方法调用和属性访问/更改,那么事情可能会简单一些,尽管我仍然缺乏对AOP的基本理解。如果您能提供任何帮助,我们将不胜感激。如果可能的话,请以初学者的水平写下你的答案(尽管我对OOP非常了解,就像我说的,我对AOP一无所知)。

你可以使用一个新的开源AOP框架来做这件事,我积极地在这个框架上工作

public class Trigger<T> : Aspect
{
    static public event EventArgs MethodCalled;
    static private Trigger<T> m_Singleton = new Trigger<T>();

    //Auto weaving aspect
    static Trigger()
    {
        Aspect.Weave<Trigger<T>>(method => method.ReflectedType == typeof(T));
    }

    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //define an advice to trigger only when method execution not failed
        yield return Advice.Basic.After.Returning(() => 
        {
            if (MethodCalled != null)
            {
                MethodCalled(this, null);
            }
        });
    }
}

public class A
{
    public void Test()
    {
    }
}

int main(string[] args)
{
    Trigger<A>.MethodCalled += ...
    new A().Test();
}
公共类触发器:方面
{
静态公共事件EventArgs MethodCalled;
静态私有触发器m_Singleton=新触发器();
//自动织造方面
静态触发器()
{
Aspect.Weave(method=>method.ReflectedType==typeof(T));
}
公共IEnumerable建议(MethodInfo方法)
{
//定义仅在方法执行未失败时触发的通知
收益返回建议.Basic.After.Returning(()=>
{
if(MethodCalled!=null)
{
MethodCalled(this,null);
}
});
}
}
公共A类
{
公开无效测试()
{
}
}
int main(字符串[]args)
{
触发

NConcern AOP框架是一个运行时工作的轻型框架。它通过继承避免工厂/代理,使用代码注入。它允许您通过注入可以使用简单委托、ILGenerator或表达式树(linq)创建的代码来向类添加方面方法之前/之后或周围。它可以处理密封类、密封方法、虚拟方法或显式/隐式接口实现

在我的示例中,我创建了一个从方面派生的类(抽象类)

当类从方面派生时,它必须通过返回Advice实例(Before/After/After.returning/After.Throwing或about)来实现Advice方法。每个类都可以使用委托或表达式来创建,以定义在方法截取时需要执行的操作

public class MyAspect : IAspect
{
    //this method is called initially (not on interception) to rewrite method body.
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //this block of code means that method will be rewrite to execute a write method name to console before original code only for public methods
        if (method.IsPublic)
        {
            yield return Advice.Basic.Before(() => Console.WriteLine(method.Name));
        }
    }
}
公共类MyAspect:IAspect
{
//最初调用此方法(不是在拦截时)重写方法体。
公共IEnumerable建议(MethodInfo方法)
{
//这段代码意味着该方法将被重写,以便在仅用于公共方法的原始代码之前,将方法名写入控制台
如果(方法IsPublic)
{
返回Advice.Basic.Before(()=>Console.WriteLine(method.Name));
}
}
}
用法

//将myaspect附加到类。将传递一个类的所有方法以建议方法处理重写方法。
Aspect.Weave(method=>method.ReflectedType==typeof(A));
//从类中分离myaspect。将重写所有方法以返回原始代码。
发布(method=>method.ReflectedType==typeof(A));

无需借助使用post-bulid IL-weaving的完整AOP框架,您就可以使用Castle并创建拦截器。您可以在网上找到大量教程:


为了让拦截器工作,您需要确保泛型类的方法和属性是虚拟的。这允许DynamicProxy的运行时编织代码生成一个包装类的代理。

我研究了一点这个问题,发现它涉及到代码编织。代码编织正在改变事情,以便调用o任何方法首先都会被重新路由到其他编织的代码来完成它。Spring.NET已经做到了这一点。因此,如果你真的想继续编写你自己的方法,你应该研究已经做到这一点的开源项目来学习。@JohnPeters我不想编写我自己的框架或代理。我想做的就是——就像前面的术语一样m AOP说,正如我通过Spring.NET学到的(谢谢)--是让我的
Trigger
类充当顾问。它将在方法返回后向从
T
类型的内部对象调用的所有方法提供建议,每个
Trigger
对象都将包含该类,该类使用方法信息从
Trigger
触发事件(与属性相同,无论是获取还是设置属性),或者类似的东西。不过,再一次,我不知道从哪里开始,即使在阅读了AOP之后。
public class MyAspect : IAspect
{
    //this method is called initially (not on interception) to rewrite method body.
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //this block of code means that method will be rewrite to execute a write method name to console before original code only for public methods
        if (method.IsPublic)
        {
            yield return Advice.Basic.Before(() => Console.WriteLine(method.Name));
        }
    }
}
//attach myaspect to A class. All methods of A will be passed to Advise method to process methods rewriting.
Aspect.Weave<MyAspect>(method => method.ReflectedType == typeof(A));

//detach myaspect from A class. All methods will be rewrite to give back original code.
Aspect.Release<MyAspect>(method => method.ReflectedType == typeof(A));