使用 DynamicProxy 仅拦截接口方法

发布于 2024-08-18 20:29:04 字数 1409 浏览 5 评论 0原文

我有一个像这样的接口

public interface IService
{
    void InterceptedMethod();
}

一个实现该接口的类,并且还有另一个方法

public class Service : IService
{
    public virtual void InterceptedMethod()
    {
        Console.WriteLine("InterceptedMethod");
    }

    public virtual void SomeMethod()
    {
        Console.WriteLine("SomeMethod");
    }
}

和一个拦截器

public class MyInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("Intercepting");
        invocation.Proceed();
    }
}

我只想拦截 IService 上存在的 Service 上的方法(即我想拦截 InterceptedMethod() 但不是 SomeMethod()),但是我不想使用 IProxyGenerationHook 中的 ShouldInterceptMethod。

我可以这样做,但由于它返回一个接口,我无法在此对象上调用 SomeMethod

var generator = new ProxyGenerator();
var proxy = generator.CreateInterfaceProxyWithTargetInterface<IService>(new Service(), new MyInterceptor());
proxy.InterceptedMethod(); // works
proxy.SomeMethod(); // Compile error, proxy is an IService

可以工作的一件事是从 SomeMethod() 中删除 virtual 并这样做,

var proxy = generator.CreateClassProxy<Service>(new MyInterceptor());

但我不这样 做不喜欢这个解决方案。

我不喜欢使用 IProxyGenerationHook 中的 ShouldInterceptMethod,因为每次更改接口时我也需要更改 ShouldInterceptMethod,而且有一天有人可以重构方法名称并且该方法不再被拦截。

还有其他方法可以做到这一点吗?

I got an interface like this

public interface IService
{
    void InterceptedMethod();
}

A class that implements that interface and also has another method

public class Service : IService
{
    public virtual void InterceptedMethod()
    {
        Console.WriteLine("InterceptedMethod");
    }

    public virtual void SomeMethod()
    {
        Console.WriteLine("SomeMethod");
    }
}

And an Interceptor

public class MyInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("Intercepting");
        invocation.Proceed();
    }
}

I want to intercept only the methods on Service that exists on IService (i.e I want to intercept InterceptedMethod() but not SomeMethod()), but I don't want to use ShouldInterceptMethod from IProxyGenerationHook.

I can do like this, but since its return an Interface, I can't call SomeMethod on this object

var generator = new ProxyGenerator();
var proxy = generator.CreateInterfaceProxyWithTargetInterface<IService>(new Service(), new MyInterceptor());
proxy.InterceptedMethod(); // works
proxy.SomeMethod(); // Compile error, proxy is an IService

One thing that can work is removing the virtual from SomeMethod() and do like this

var proxy = generator.CreateClassProxy<Service>(new MyInterceptor());

But I don't like this solution.

I dont like using ShouldInterceptMethod from IProxyGenerationHook, because everytime that I change the interface I also need to change ShouldInterceptMethod, also someone someday can refactor the method name and the method is not intercepted anymore.

There's any other way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

骷髅 2024-08-25 20:29:04

如果要为类创建代理,则需要使用classproxy。

如果您想排除某些成员,则必须使用 IProxyGenerationHook。

如果您希望您的代码对接口/类成员的更改(例如添加或删除的名称签名)不可知 - 那么就这样做吧!

我能想到的最简单的代码是这样的:

private InterfaceMap interfaceMethods = typeof(YourClass).GetInterfaceMap(typeof(YourInterface));
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
   return Array.IndexOf(interfaceMethods.ClassMethods,methodInfo)!=-1;
}

If you want to create a proxy for the class, you need to use classproxy.

If you want to exclude certain members you have to use IProxyGenerationHook.

If you want your code to be agnostic to changes to members of interface/class like names signatures being added or removed - than make it so!

Simplest code I could think of is something like this:

private InterfaceMap interfaceMethods = typeof(YourClass).GetInterfaceMap(typeof(YourInterface));
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
   return Array.IndexOf(interfaceMethods.ClassMethods,methodInfo)!=-1;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文