简体   繁体   English

在C#中使用反射的方法拦截

[英]Method Interception using Reflection in C#

I wrote an abstract class that uses reflection to find fields marked with an Attribute in the constructor, like this: 我编写了一个抽象类,该类使用反射在构造函数中查找带有Attribute标记的字段,如下所示:

[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute {}

public class ATrackedObject {
    public ATrackedObject() {
        Type objType = this.GetType();
        foreach(FieldInfo f in objType.GetFields()) {
            if(f.IsDefined(typeof(TrackedField)), false)) {
                //Add field to list to keep tabs on periodically
            }
        }
    }
}

What I would like to do, is: 我想做的是:

  1. Create another attribute, TrackedMethod 创建另一个属性TrackedMethod
  2. In the constructor, in the same fashion as with the TrackedFields, find all methods tagged with TrackedMethod 在构造函数中,以与TrackedFields相同的方式,找到所有用TrackedMethod标记的方法
  3. Change the method so that when it gets called, a method inside ATrackedObject gets called first or instead, either by replacing the method entirely or by injecting code into it, but without breaking the ability to at least see what the original method call was, including parameters 更改方法,以便在调用该方法时,首先或通过完全替换该方法或向其中注入代码来调用ATrackedObject内部的方法,而又不破坏至少看到原始方法调用是什么的能力,包括参数
  4. No third-party libaries , and should be .NET 3.5 compatible 没有第三方库 ,并且应与.NET 3.5兼容

I have seen a number of SE threads discussing how to do this, and all of the answers relied on being able to use a third party library - however, none of the questions seemed to match my use case exactly - I can ensure 100% that every object that needs to have methods tracked will inherit from the class that does the tracking. 我已经看到许多SE线程在讨论如何执行此操作,所有答案都取决于能够使用第三方库-但是,所有问题似乎都不完全符合我的用例-我可以确保100%每个需要跟踪方法的对象都将从进行跟踪的类继承。

I don't know for sure this is possible, but I am wondering since IoC/AOP libraries like PostSharp and others exist, surely they must operate by some kind of mechanism - I assume Reflection.Emit plays a part - but what, and how? 我不确定这是否可行,但我想知道自从IoC / AOP库(如PostSharp等)存在以来,它们肯定必须通过某种机制运行-我认为Reflection.Emit发挥了作用-但作用和方式?

Here are some similar questions, which did not have what seemed to me to be answers to my specific scenario, or relied on third party libraries: 这是一些类似的问题,在我看来,这些问题并没有解决我的特定情况,或者没有依赖第三方库:

custom-attribute-to-process-info-before-a-method-is-called 自定义属性对工艺信息前方的一个法,是所谓的

how-do-i-intercept-a-method-call-in-c (this was helpful, but missing the crucial component of how to actually inject code 我如何在C语言中拦截方法调用 (这很有用,但缺少了如何实际注入代码的关键组成部分

intercept-method-calls 截距法通话

Is there a way to make this technique (Attribute -> Base Class Constructor -> Reflection -> Method Interception) viable? 有没有办法使这种技术(属性->基类构造函数->反射->方法拦截)可行?

Could something like this work for what you need? 这样的东西可以满足您的需求吗?

[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute { }

public class ATrackedObject
{
    public ATrackedObject()
    {
        Type objType = this.GetType();
        foreach (FieldInfo f in objType.GetFields())
        {
            if (f.IsDefined(typeof(TrackedField), false)) {
                if (f.FieldType == typeof(Action))
                {
                    var currentValue = f.GetValue(this) as Action;
                    Action newValue = () =>
                    {
                        Console.WriteLine($"Tracking {f.Name}");
                        currentValue.Invoke();
                    };

                    f.SetValue(this, newValue);
                }
            }
        }
    }

    [TrackedField]
    public Action SomeMethod = () => Console.WriteLine("Some Method Called");
}

this is done with a simple Action property but it could be extended to use Func<> 这是通过简单的Action属性完成的,但可以扩展为使用Func<>

edit: forgot to include usage and output. 编辑:忘记包括用法和输出。

usage: 用法:

static void Main(string[] args)
{
    var obj = new ATrackedObject();
    obj.SomeMethod();

    Console.Read();
}

output: 输出:

Tracking SomeMethod
Some Method Called

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM