Отслеживать обращение к классу

182
08 мая 2019, 00:20

У меня есть класс - api для работы с sql, иногда проседает интернет, и приходится повышать время прерывания с 50 мс до 75-90. Я хочу сделать, так чтобы при 20 любых успешных вызовов методов из этого класса возвращалось время обратно до 50 mc. Методов 70, обращений из кода более 350.

Возможно ли отслеживать обращение к моему классу ApiData или как мне поступить?

Answer 1

Я когда-то делал логгирование с помощью AOP Например. У вас есть класс, который нужно отcелживать. Помечаете его атрибутом. В моем случае это HelloWorld

[HelloWorld]
public class SomeService1 : MarshalByRefObject
{
    public void Method1()
    {
        Console.WriteLine("SomeService1.Method1");
    }
}

Далее определяем сам атрибут и обработчик

public sealed class HelloWorldAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new HelloWorldCallHandler();
    }
}
public class HelloWorldCallHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        //В этом месте происходит вызов метода, помеченного атрибутом
        //либо любого метода класса, если класс целиком помечен
        var result = getNext()(input, getNext);
        stopwatch.Stop();
        Console.WriteLine(stopwatch.Elapsed);
        return result;
    }
    public int Order { get; set; }
}

Ну и регистрируем все это дело в IoC контейнере

IUnityContainer container = new UnityContainer();
        container
            .AddNewExtension<Interception>()
            .Configure<Interception>()
            .SetDefaultInterceptorFor<SomeService1>(new TransparentProxyInterceptor());
        var s = container.Resolve<SomeService1>();
        s.Method1();

Теперь, при вызове методов класса через контейнер, можно это отследить. Проблема в том, что нужны будут теперь ссылки на контейнер или объект, что в нем лежит.

Answer 2

Только счетчиком.

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

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

Answer 3

Если эту работу с бд можно реализовать через Singleton, то мне пришел в голову такой хак)

public sealed class Worker
{
    private static readonly Lazy<Worker> lazy = new Lazy<Worker>(() => new Worker());
    private static int counter;
    public static Worker Instance
    {
        get
        {
            counter++;
            return lazy.Value;
        }
    }
    public void MegaMethod(){}
    public void SuperMethod(){}
    public int GetMethodCounter()
    {
        return counter;
    }
}

Соответственно вот так будет работать:

Worker.Instance.MegaMethod();
Worker.Instance.SuperMethod();
int count = Worker.Instance.GetMethodCounter();

Однако если обращаться так, то не будет :(

var worker = Worker.Instance;
worker.MegaMethod();
worker.SuperMethod();
int count = worker.GetMethodCounter());
READ ALSO
Приведение типов с помощью GetType()

Приведение типов с помощью GetType()

Как совершить приведение типов, если конечный тип заранее неизвестен?

146
Подключение к базе данных без клиента

Подключение к базе данных без клиента

 Подскажите пожалуйста в следующем вопросе - нужно ли устанавливать Oracle Client на мою Windows машину для работы с БД и разработки клиентского...

150
Как выйти на новый уровень в разработке C# [закрыт]

Как выйти на новый уровень в разработке C# [закрыт]

Может я немного не туда пишу, но все жеЯ учусь на 3 курсе универа, учат так себе, куча ненужных предметов было, впрочем как и везде наверное

155
Не отображаются данные таблицы в dataGridView

Не отображаются данные таблицы в dataGridView

встретился со следующей проблемой, работал с БД, делал различные операции, потом решил добавить ещё одну таблицуПосле ее добавления, когда...

157