Какой шаблон можно использовать, чтобы избежать создания ненужных блоков из конвейера? - PullRequest
4 голосов
/ 25 сентября 2019

Мое приложение ASP.NET Core использует наши собственные конвейеры для обработки запросов.Каждый конвейер содержит 1+ блоков, а количество блоков не имеет ограничений.в реальном случае это может быть до 200+ блоков, конвейер будет проходить через все блоки в последовательности из конфигурации, например:

Pipeline<DoActionsPipeline>().AddBlock<DoActionAddUserBlock>().AddBlock<DoActionAddUserToRoleBlock>()... 

Как в примере выше (только в качестве примера), и существует 200+ блоки, сконфигурированные в этом конвейере, блоки могут быть DoActionAddUserBlock, DoActionAddUserToRoleBlock, DoActionAddAddressToUserBlock и так далее.многие действия смешаны в одном конвейере.(Пожалуйста, не спрашивайте, зачем смешивать их, это просто пример, это не имеет значения для моего вопроса.)

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

Вот пример кода, не очень хороший, но он показывает мою боль:

public class DoActionAddUserBlock : BaseBlock<User, User, Context>
{
    public override User Execute(User arg, Context context)
    {
        if (context.ActionName != "AddUser")
        {
            return arg;
        }

        return AddUser(arg);
    }

    protected User AddUser(User user)
    {
        return user;
    }
}

public abstract class BaseBlock<TArg, TResult, TContext>
{
    public abstract TResult Execute(TArg arg, TContext context);
}

public class Context
{
    public string ActionName { get; set; }
}
public class User
{

}

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

[Condition("Action==AddUser")] // or [Action("AddUser")] // or [TypeOfArg("User")]
public class DoActionAddUserBlock : BaseBlock<User, User, Context>
{
    public override User Execute(User arg, Context context)
    {
        return AddUser(arg);
    }

    //...
}

1 Ответ

2 голосов
/ 27 сентября 2019

Пожалуйста, покажите нам метод Pipeline<T>() (это метод или класс?), Потому что он необходим для точного ответа.

В любом случае, я хочу приложить все усилия стекущая информация.

Ваша цель "Я хочу условно скопировать блоки" , поэтому вам нужно переместить ваше условие в контекст вне экземпляра, что вы можете сделать с атрибутами:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ActionNameAttribute : Attribute
{
    public ActionNameAttribute(string name)
    {
        this.Name = name;
    }

    public string Name { get; }
}

[ActionName(nameof(AddUser))]
public class DoActionAddUserBlock : BaseBlock<User, User, Context>
{
    public override User Execute(User arg, Context context)
    {
        return AddUser(arg);
    }
}

Затем выполните проверку в методе .AddBlock<T>() (что, мне кажется, что-то в этом роде):

public YourUnknownType<T> AddBlock<TBlock>()
{
    var type = typeof(TBlock);
    var attributes = attributes.GetCustomAttributes(typeof(string), inherit: true); // or false if you don't need inheritation
    var attribute = attributes.FirstOrDefault() as ActionNameAttribute;

    if (attribute.Name == this.Context.ActioName)
    {
        // place here the block init
    }

    return AnythingYouActuallyReturn();
}

Надеюсь, это поможет!

...