Можно ли создать динамический прокси для статического класса или статического метода в C #? - PullRequest
1 голос
/ 23 апреля 2010

Я пытаюсь придумать, как (статический или экземплярный) вызов метода может быть перехвачен динамическим прокси. Я хочу реализовать его как c # методы расширения , но застрял на том, как генерировать динамический прокси для статических методов.

Некоторые использования:

Repository.GetAll<T>().CacheForMinutes(10);
Repository.GetAll<T>().LogWhenErrorOccurs();

//or     
var repo = new Repository();
repo.GetAll<T>().CacheForMinutes(10);
repo.GetAll<T>().LogWhenErrorOccurs();

Я открыт для любой библиотеки (linfu, castle.dynamic proxy 2 или др.).

Спасибо!

Ответы [ 2 ]

9 голосов
/ 23 апреля 2010

Абсолютно невозможно.

На самом деле прокси не может быть сгенерирован даже на всех экземплярах методов - они должны быть виртуальными, чтобы прокси-генератор мог создать производный класс и переопределить его.

Статические методы никогда не являются виртуальными, и поэтому не могут быть переопределены прокси.

(Технически существует обходной путь для не виртуальных методов, который заключается в извлечении класса из MarshalByRefObject, но решения на основе удаленного взаимодействия для этого медленны и неуклюжи и по-прежнему не поддерживают статические методы.)

Учитывая, что ваш класс называется Repository, я собираюсь предложить вам вместо этих методов создать методы экземпляра. Такие операции обычно не должны начинаться с static. Если вы сделаете их static, вы потеряете много вещей: слабую связь, насмешки, внедрение зависимостей, определенную степень тестируемости модулей и - как вы только что обнаружили - проксирование и перехват.

0 голосов
/ 11 декабря 2016

Невозможно при обычных стратегиях перехвата.

Но большинство AOP Framework, работающих во время компиляции, могут это сделать. (пример: PostSharp)

Я работаю с открытым исходным кодом NConcern AOP Framework .

Это простая .NET AOP Framework, позволяющая перехватывать во время выполнения путем обмена методами.

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

Моя рекомендация - избегать использования AOP для «обезьяньего патча», а статические методы должны быть только «синглтонными ярлыками», а не обычным потоком.

в вашем случае проще использовать одноэлементный шаблон со статическими методами, такими как shortcup и DI (Dependency Injection), чтобы включить простой прокси-шаблон.

Пример:

интерфейс

public interface IRepository
{
    IQueryable<T> Query<T>()
        where T : class;
}

сахар с использованием DI (через фабрику)

static public class Repository
{
    //You can wrap the interface (proxy) here if you need...
    static private readonly IRepository m_Repository = MyDIFactory.Import<IRepository>();

    static public IQueryable<T> Query<T>()
        where T : class
    {
        return Repository.m_Repository.Query<T>();
    }
}

Использование

Repository.Query<T>().CacheForMinutes(10);
Repository.Query<T>().LogWhenErrorOccurs();
...