C# 中使用反射进行方法拦截

2024-01-05

我编写了一个抽象类,它使用反射来查找构造函数中标有属性的字段,如下所示:

[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
            }
        }
    }
}

我想做的是:

  1. 创建另一个属性 TrackedMethod
  2. 在构造函数中,在 与 TrackedFields 相同的方式,查找标记为的所有方法 追踪法
  3. 更改该方法,以便在调用该方法时, ATrackedObject 内部的方法首先被调用,或者通过 完全替换该方法或通过向其中注入代码,但是 在不破坏至少看到原始内容的能力的情况下 方法调用是,包括参数
  4. 没有第三方库,并且应该兼容 .NET 3.5

我已经看到许多 SE 线程讨论如何做到这一点,并且所有答案都依赖于能够使用第三方库 - 然而,没有一个问题似乎与我的用例完全匹配 - 我可以确保 100%每个需要跟踪方法的对象都将从执行跟踪的类继承。

我不确定这是否可能,但我想知道由于像 PostSharp 等 IoC/AOP 库存在,它们肯定必须通过某种机制进行操作 - 我假设 Reflection.Emit 发挥了作用 - 但是什么以及如何操作?

以下是一些类似的问题,在我看来,这些问题没有适合我的特定场景的答案,或者依赖于第三方库:

调用方法之前的自定义属性到进程信息 https://stackoverflow.com/questions/17596688/custom-attribute-to-process-info-before-a-method-is-called

如何在 C 中拦截方法调用 https://stackoverflow.com/questions/25803/how-do-i-intercept-a-method-call-in-c(这很有帮助,但缺少如何实际注入代码的关键组成部分

拦截方法调用 https://stackoverflow.com/questions/25366243/intercept-method-calls

有没有办法使这种技术(属性 -> 基类构造函数 -> 反射 -> 方法拦截)可行?


这样的东西可以满足您的需要吗?

[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");
}

这是通过一个简单的Action财产,但可以扩展使用Func<>

编辑:忘记包括用法和输出。

usage:

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

    Console.Read();
}

output:

Tracking SomeMethod
Some Method Called
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中使用反射进行方法拦截 的相关文章

随机推荐