2009-06-12 16 views
7

Potrzebuję pomocy - Próbuję użyć niestandardowego atrybutu sprawdzania poprawności w projekcie sieci Web ASP.NET MVC, który musi wykonać wywołanie bazy danych.Wstrzykiwanie bazy danych do atrybutu sprawdzania poprawności za pomocą ASP MVC i Castle Windsor

Mam windsor pomyślnie działa dla kontrolerów i interfejs IRepository jest wstrzykiwany normalnie. Problem pojawia się, gdy muszę wstrzyknąć repozytorium do klasy atrybutów.

Klasa atrybut ma następujący kod:

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; 
    } 

Moim problemem jest to, że nie wydaje się, aby Windsor przechwycić contruction atrybutu przejść w IArticleRepository

aktualny kod w moim globalny Plik .asax wygląda następująco:

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

Każda pomoc zostanie bardzo doceniona.

Odpowiedz

5

Kontener AFAIK o braku zależności może bezpośrednio zarządzać atrybutem, ponieważ jest tworzony przez środowisko wykonawcze i nie ma możliwości przechwycenia tego.

Jednak mogą one oszukać przez:

  1. Używanie statycznego bramę do pojemnika (example) lub
  2. Używając „sklejenia”, która wstrzykuje cokolwiek zależności są znalezione w obrębie już -konstruowany obiekt. Nazywa się to BuildUp in Unity lub InjectProperties in Autofac.

Windsor nie obsługuje # 2 (ref1, ref2), więc można:

  1. Spróbuj jeden z hacków do Windsor wsparcie # 2 (hack1, hack2)
  2. Użyj a static gateway
  3. Zaimplementuj swój własny IValidatorBuilder i użyj Windsora do utworzenia walidatorów. Jestem pewien, że jest to gdzieś zaimplementowane, ale nie mogę tego teraz znaleźć ...
+0

Wielkie dzięki. Wybrałam # 1, który idealnie spełnia moje potrzeby. –

-1

Hmm.

Czy możesz przetestować efekt usunięcia ctor (ciąg znaków) i sprawdzić, czy to przynajmniej zmusza Castle do użycia ctor z Repostiory?

W przeciwnym razie nazywamy AddComponent (nazwa, typ, typ). Poza tym to naprawdę powinno zadziałać ...

Czy ta wskazówka pojawia się na mój pierwszy pomysł? How do I use Windsor to inject dependencies into ActionFilterAttributes

+0

Niestety, nie mogę usunąć konstruktor ciąg jako atrybut wygląda następująco: [ValidateUniqueUrlNode („Proszę podać unikalny URL”)] public string UrlNode {get; zestaw; } Czy to powinno być inne? –

+0

Dahhh. Nadal drapię głowę ... Będę musiał poszukać – penderi

0

Nie wiem, czy to pomoże, ale podklasy ValidationAttribute narazić Resolve<T>() metodę tak:

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

Wtedy może on być stosowany w każdym zwyczajem ValidatorAttribute który musi trafić do bazy danych:

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

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

Myślę, że jest to odmiana podejścia "bramy statycznej", o której wspomniał Mauricio Scheffer. Nie wiem, czy to dobry projekt, czy nie. Nie jestem wielkim fanem tego, wolałbym, żeby zależność została wstrzyknięta bardziej "elegancko", chociaż oczywiście nie mogę użyć zastrzyku konstruktora, chciałbym użyć zastrzyku własności, ale nie mogę wymyślić sposobu na przechwyć się do kodu ramowego ASP.NET MVC, aby to zrobić (nawet poznałem kod źródłowy MVC2).

+0

Skąd bierze się IocHelper? – soniiic

+3

@soniiic wygląda jak zły szum –

0

udało mi się podłączyć go do góry [użyciem Autofac jak to się dzieje, ale to tylko zastrzyk konstruktor za pośrednictwem ASP.NET MVC DependencyResolver] in this answer, umożliwiając jedną napisać:

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); 
    } 
} 

W niektórych klasach pomocniczych (spójrz tam), podłącz go np w ASP.NET MVC jak więc w Global.asax: -

DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
    typeof(ValidatorServiceAttribute), 
    (metadata, context, attribute) => 
     new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));