0

I'm building a mvc webapp that shares model objects with an existing winforms app. I'm introducing VAB validation into it. One of the items I need to validate is an int that can be one of x levels.

I've written a LevelValidator, but it needs to have the levels accessible.

Regarding the new call in this code, it looks like I should inject the LevelValidator instead of Levels? Other ways?

public class LevelValidatorAttribute : ValueValidatorAttribute
{
    protected override Microsoft.Practices.EnterpriseLibrary.Validation.Validator DoCreateValidator(Type targetType)
    {
        LevelValidator validator = new LevelValidator();
        validator.Levels = this.Levels;
        return validator;
    }

    [Dependency]
    public Levels Levels { get; set; }
}
Community
  • 1
  • 1
Carl R
  • 8,104
  • 5
  • 48
  • 80

1 Answers1

1

You can't use dependency injection on attributes, because attributes are not controlled and created by a dependency injection framework, but controlled by the CLR itself. Try having a design were your attribute does not need dependency injection.

If all fails, you can use the Service Locator pattern inside the LevelValidator (best to leave the attribute allone) and make a call to the unity container from within the LevelValidator class. For this to work, you need to have a static field that holds the container. For instance:

public class LevelValidator : Validator
{
    public static UnityContainer Container { get; set; }

    public LevelValidator()
    {
        this.Levels = Container.Resolve<Levels>();
    }

    public Levels Levels { get; set; }
}

In the startup path of your application you need to set this static Container property, as follows:

public void Main()
{
    var container = new UnityContainer();

    // configure it

    LevelValidator.Container = container;
}

This solution is far from ideal and should be prevented in most cases. However, the creation of the attribute and the LevelValidator is outside the control of Unity.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • I believe that this type of design can be prevented when doing configuration based validation. In that case VAB allows you to intercept and replace certain parts, which allows you to create validators using dependency injection. One warning though: I've browsed the VAB source a bit and didn't find an easy way to do this. I expect you would need to replace a considerable part of the VAB infrastructure, starting at the `ConfigurationValidatorFactory`. I won't advice burning your time on that. – Steven Apr 20 '11 at 07:49
  • I ended up with this: `public abstract class InjectedValueValidatorAttribute : ValueValidatorAttribute { public static IUnityContainer Container { get; set; } }` – Carl R Apr 20 '11 at 11:17