Перехватывать только методы интерфейса с DynamicProxy - PullRequest
1 голос
/ 21 января 2010

У меня есть такой интерфейс

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 (т.е. я хочу перехватывать InterceptedMethod (), но не SomeMethod ()), но я не хочу использовать ShouldInterceptMethod из IProxyGenerationHook.

Я могу сделать это, но так как он возвращает интерфейс, я не могу вызвать 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

Единственное, что может сработать, - это удалить virtual из SomeMethod () и сделать так:

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

Но мне не нравится это решение.

Мне не нравится использовать ShouldInterceptMethod из IProxyGenerationHook, потому что каждый раз, когда я меняю интерфейс, мне также нужно менять ShouldInterceptMethod, также кто-то когда-нибудь может изменить рефакторинг имени метода, и метод больше не перехватывается.

Есть ли другой способ сделать это?

1 Ответ

2 голосов
/ 21 января 2010

Если вы хотите создать прокси для класса, вам нужно использовать classproxy.

Если вы хотите исключить определенных участников, вы должны использовать IProxyGenerationHook.

Если вы хотите, чтобы ваш код не зависел от изменений членов интерфейса / класса, таких как добавление или удаление сигнатур имен, - сделайте это так!

Простейший код, который я мог придумать, выглядит примерно так:

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