Украсить метод с помощью пользовательских атрибутов - PullRequest
3 голосов
/ 09 марта 2011

У меня есть некоторые функции, для которых я хочу регистрировать время, затраченное на них.

DBResult LongTask(DBCommand command)
{
   ...
}

Есть ли способ добиться этого

[LogTimeUsed()]
DBResult LongTask(DBCommand command)
{
   ...
}

Чтобы у меня где-нибудь был класс / функция, которая вызывается каждый раз, когда вызывается эта функция, и я могу ввести свой собственный код, получить доступ к команде и DBResult и время, проведенное в функции?

Ответы [ 6 ]

4 голосов
/ 09 марта 2011

Нет встроенного способа сделать это в .NET.

Если вы хотите , а не , чтобы использовать какие-либо сторонние библиотеки (как вы сказали в одном из ваших комментариев),выполнение ткачества кода или генерация динамического прокси - это большая работа.В этом случае лучше отказаться от использования атрибутов и использовать шаблон проектирования декоратора.Вот пример:

// Define an interface for the operation
public interface IMyLongRunningTask
{
    DBResult longTask(DBCommand command);
}

// Define an implementation for the operation:
public class MyLongRunningTask : IMyLongRunningTask
{
    public DBResult longTask(DBCommand command)
    {
        // code here
    }
}

И теперь вы можете написать декоратор для IMyLongRunningTask:

public class MyLongRunningTaskMonitor : IMyLongRunningTask
{
    private readonly IMyLongRunningTask wrappedService;
    private readonly ILogger logger;

    public MyLongRunningTaskMonitor(IMyLongRunningTask wrapped,
        ILogger logger)
    {
        this.wrappedService = wrapped;
        this.logger = logger;
    }

    public DBResult longTask(DBCommand command)
    {
        var watch = Stopwatch.CreateNew();

        var result = this.wrappedService.longTask(command);

        this.logger.Log("longTask executed in " + 
            watch.ElapsedMilliseconds + " ms.");

        return result;
    }
}

Когда вы используете внедрение зависимостей, вы можете легко настроить MyLongRunningTaskMonitor для возвратакогда запрашивается IMyLongRunningTask.Например:

container.Register<IMyLongRunningTask>(() =>
    new MyLongRunningTaskMonitor(
        container.GetInstance<MyLongRunningTask>(),
        container.GetInstance<ILogger>()
    )
);
2 голосов
/ 09 марта 2011

Вы можете использовать Castle DynamicProxy .

DynamicProxy генерирует прокси для ваши объекты, которые вы можете использовать для прозрачно добавлять или изменять поведение их, обеспечить до / после обработки и многое другое.

0 голосов
/ 26 мая 2017

Вопрос состоит в том, чтобы найти способ создать декоратор в c # с помощью атрибутов c #, чтобы попытаться создать синтаксис декоратора, как это видно на python (что превосходно ... сообщество C # принимает к сведению)

Нечто подобное можно было бы получить, внедрив «атрибут» в имя вашего метода (например, LongTask_LogTimeUsed), а затем иметь небольшой (кодовый) код ВНУТРИ метода LongTask, который считывает его имя метода, делегируя предварительную или последующую обработку соответствующим обработчики:

Как получить название текущего метода из кода

Хотя для передачи параметров в пре- или постпроцессоры нужно подумать.

0 голосов
/ 26 мая 2017

Просто для добавления в список сторонних материалов есть Spring AOP (Spring - это большой и популярный фреймворк, портированный на .net из Java)

0 голосов
/ 09 марта 2011

Вы можете сделать это, используя PostSharp

Также проверьте ответ на мой вопрос по SO - Аспектно-ориентированное ведение журнала с Unity \ T4 \ что-нибудь еще

0 голосов
/ 09 марта 2011

Если вы не обрабатываете этот конкретный тип атрибута самостоятельно, вам следует изучить Аспектно-ориентированное программирование, используя что-то вроде PostSharp

...