C # настраиваемый атрибут для метода, включая использование ключевого слова - PullRequest
0 голосов
/ 11 мая 2019

Мне нужно подготовить пользовательский Attribute, который может работать как оператор using.

Итак, метод ниже

private async Task<List<TermUserEmailInformationDto>> GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu()
{
    using (_unitOfWorkManager.Current.DisableFilter(GlobalConstants.DataFilters.MustHaveTermId))
    {
        // Code goes on...
    }
}

должно быть как:

[DisableFilter(GlobalConstants.DataFilters.MustHaveTermId)]
private async Task<List<TermUserEmailInformationDto>> GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu()
{
    // Code goes on...
}

Есть ли способ сделать это?

1 Ответ

1 голос
/ 11 мая 2019

Я предлагаю такой атрибут:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
internal class DisableFilterAttribute : Attribute
{
    public DataFilter DataFilter { get; }
    public DisableFilterAttribute(DataFilter dataFilter) => DataFilter = dataFilter;
}

enum DataFilter
{
    MustHaveTermId,
    SomeFilter,
    AnotherFilter
}

Ограничение разума для параметров атрибута.

Согласно коду в вопросе UnitOfWorkManager должно выглядеть так:

internal class UnitOfWorkManager : IDisposable
{
    public UnitOfWorkManager Current { get; private set; }

    public UnitOfWorkManager()
    {
        Current = this;
    }

    public UnitOfWorkManager DisableFilter(DataFilter dataFilter)
    {
        var manager = new UnitOfWorkManager();
        Console.WriteLine($"Created  UnitOfWorkManager {manger.GetHashCode()} with {dataFilter} disabled");
        return manager;
    }

    public void Dispose() { Console.WriteLine($"Disposed UnitOfWorkManager {GetHashCode()}"); }
}

Я предлагаю изменить UnitOfWorkManager таким способом:

public void DoWithFilters(Action action)
{
    var current = Current;

    var managers = new List<UnitOfWorkManager>();
    foreach (var attribute in
                new StackTrace().GetFrame(1).GetMethod().GetCustomAttributes(false).OfType<DisableFilterAttribute>())
        managers.Add(Current = Current.DisableFilter(attribute.DataFilter));

    action();

    managers.Reverse();
    foreach (var manager in managers)
        manager.Dispose();

    Current = current;
}

Можно использовать это так:

[DisableFilter(DataFilter.MustHaveTermId)]
[DisableFilter(DataFilter.SomeFilter)]
private Task<List<TermUserEmailInformationDto>> GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu()
{
    Task<List<TermUserEmailInformationDto>> result = null;
    _unitOfWorkManager.DoWithFilters(() =>
    {
        Console.WriteLine("Performing GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu");
        // Code goes on...
    });
    return result;
}

Запуск

Console.WriteLine($"Before method called Current is {_unitOfWorkManager.Current.GetHashCode()}");
GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu();
Console.WriteLine($"After  method called Current is {_unitOfWorkManager.Current.GetHashCode()}");

Дает результат как:

Before method called Current is 46104728
Created  UnitOfWorkManager 21083178 with MustHaveTermId disabled
Created  UnitOfWorkManager 30015890 with SomeFilter disabled
Performing GetAllTermUserEmailAddressesHedefBelirlemeDirektorVeUstu
Disposed UnitOfWorkManager 30015890
Disposed UnitOfWorkManager 21083178
After  method called Current is 46104728

Вот ссылка на код выше одним куском

...