Внедрение базы данных в атрибут проверки с помощью ASP MVC и Castle Windsor - PullRequest
7 голосов
/ 12 июня 2009

Мне нужна помощь - я пытаюсь использовать пользовательский атрибут проверки в веб-проекте ASP.NET MVC, который должен выполнить вызов базы данных.

Виндзор успешно работает для контроллеров, и интерфейс IRepository вводится нормально. Проблема возникает, когда мне нужно вставить хранилище в класс атрибута.

Класс атрибута имеет следующий код:

public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
    private readonly string message;
    private readonly IArticleRepository articleRepository;

    public ValidateUniqueUrlNodeAttribute(string message)
    {
        this.message = message;
    }

    public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
    {
        this.articleRepository = articleRepository;
    }
    public override IValidator Build()
    {
        var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };

        ConfigureValidatorMessage(validator);

        return validator;
    }

Моя проблема в том, что я не могу заставить Виндзор перехватывать конструкцию атрибута для передачи в IArticleRepository

Текущий код в моем файле global.asax выглядит следующим образом:

container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
   container
     .RegisterControllers(Assembly.GetExecutingAssembly())
     .AddComponent<IArticleRepository, ArticleRepository>()
     .AddComponent<ValidateUniqueUrlNodeAttribute>();

Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

5 голосов
/ 12 июня 2009

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

Однако они могут обмануть любым из:

  1. Использование статического шлюза в контейнер ( пример ) или
  2. Использование функции "BuildUp", которая внедряет любые зависимости, найденные в уже построенном объекте. Это называется BuildUp в Unity или InjectProperties в Autofac .

Windsor не поддерживает # 2 ( ref1 , ref2 ), поэтому вы можете:

  1. Попробуйте один из хаков, чтобы Виндзор поддерживал # 2 ( hack1 , hack2 )
  2. Использовать статический шлюз
  3. Реализуйте свой собственный IValidatorBuilder и заставьте его использовать Windsor для создания валидаторов. Я уверен, что это где-то реализовано, но я не могу найти это прямо сейчас ...
0 голосов
/ 05 февраля 2016

Я смог подключить его [используя Autofac, как это происходит, но это всего лишь инжекция конструктора через ASP.NET MVC DependencyResolver] в этом ответе , что позволило написать:

class MyModel 
{
    ...
    [Required, StringLength(42)]
    [ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
    public string MyProperty { get; set; }
    ....
}

public class MyDiDependentValidator : Validator<MyModel>
{
    readonly IUnitOfWork _iLoveWrappingStuff;

    public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
    {
        _iLoveWrappingStuff = iLoveWrappingStuff;
    }

    protected override bool IsValid(MyModel instance, object value)
    {
        var attempted = (string)value;
        return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
    }
}

С некоторыми вспомогательными классами (посмотрите там), вы подключаете его, например. в ASP.NET MVC как в Global.asax: -

DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
    typeof(ValidatorServiceAttribute),
    (metadata, context, attribute) =>
        new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
0 голосов
/ 28 февраля 2010

Не знаю, помогает ли это, но я подкласс ValidationAttribute выставил Resolve<T>() метод, подобный следующему:

public abstract class IocValidationAttribute : ValidationAttribute
{
    protected T Resolve<T>()
    {
        return IocHelper.Container().Resolve<T>();
    }
}

Затем его можно использовать в любом пользовательском атрибуте ValidatorAttribute, который должен попасть в базу данных:

public class UniqueEmailAttribute : IocValidationAttribute
{
    public override bool IsValid(object value)
    {
        ICustomerRepository customerRepository = Resolve<ICustomerRepository>();

        return customerRepository.FindByEmail(value.ToString()) == null;
    }
}

Я думаю, что это вариант подхода «Статические Врата», упомянутый Маурисио Шеффером. Я не знаю, хороший это дизайн или нет. Я не большой поклонник этого, я бы предпочел, чтобы зависимость была введена более «элегантно», хотя я, очевидно, не могу использовать инъекцию в конструктор, я бы хотел использовать инъекцию свойства, но не могу найти способ для этого подключитесь к коду фреймворка ASP.NET MVC (я даже изучал исходный код MVC2).

0 голосов
/ 12 июня 2009

Хм.

Можете ли вы проверить эффект удаления ctor (строковое сообщение) и посмотреть, заставит ли Касл использовать ctor вместе с Repostiory?

В противном случае мы вызываем AddComponent (имя, тип, тип). Кроме того, это действительно должно работать ...

Также это намекает на мою первую идею? Как использовать Windsor для внедрения зависимостей в ActionFilterAttributes

...