MVC2 中的 Autofac 与 FluentValidation

发布于 2024-09-27 08:50:03 字数 1522 浏览 3 评论 0原文

我在 ValidatorFactory.CreateInstance 调用执行期间收到“未注册错误”。看来发送到该方法的类型是正确的。

我的注册代码:

...
builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.EndsWith("Validator")).As<IValidator>();
builder.Register(d => _containerProvider).As<IContainerProvider>();
builder.Register(d => new ValidatorFactory(_containerProvider.ApplicationContainer.Resolve<IContainerProvider>())).As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

我的 ValidatorFactory 代码:

public class ValidatorFactory : ValidatorFactoryBase {
    private readonly IContainerProvider _containerProvider;

    public ValidatorFactory(IContainerProvider containerProvider) {
        _containerProvider = containerProvider;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _containerProvider.ApplicationContainer.Resolve<IValidator>(validatorType);
    }
}

我的视图模型和验证器代码:

[Validator(typeof(EmployeeViewModelValidator))]
public class EmployeeViewModel {
    public EmployeeViewModel() {}
    public EmployeeViewModel(string firstName) {
        FirstName = firstName;
    }

    public string FirstName { get; private set; }
}

public class EmployeeViewModelValidator : AbstractValidator<EmployeeViewModel> {
    public EmployeeViewModelValidator() {
        RuleFor(x => x.FirstName)
            .NotEmpty();
    }
}

我最好的猜测是我注册的验证器是错误的。

I'm getting a 'not registered error' during execution in the ValidatorFactory.CreateInstance call. It appears the type being sent into the method is correct.

My registration code:

...
builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.EndsWith("Validator")).As<IValidator>();
builder.Register(d => _containerProvider).As<IContainerProvider>();
builder.Register(d => new ValidatorFactory(_containerProvider.ApplicationContainer.Resolve<IContainerProvider>())).As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

My ValidatorFactory code:

public class ValidatorFactory : ValidatorFactoryBase {
    private readonly IContainerProvider _containerProvider;

    public ValidatorFactory(IContainerProvider containerProvider) {
        _containerProvider = containerProvider;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _containerProvider.ApplicationContainer.Resolve<IValidator>(validatorType);
    }
}

My view model and validator code:

[Validator(typeof(EmployeeViewModelValidator))]
public class EmployeeViewModel {
    public EmployeeViewModel() {}
    public EmployeeViewModel(string firstName) {
        FirstName = firstName;
    }

    public string FirstName { get; private set; }
}

public class EmployeeViewModelValidator : AbstractValidator<EmployeeViewModel> {
    public EmployeeViewModelValidator() {
        RuleFor(x => x.FirstName)
            .NotEmpty();
    }
}

My best guess is that I'm registering the validators wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

迟到的我 2024-10-04 08:50:03

要从实现 IValidator 的多个类中进行解析,autofac 文档 显示了几种技术。我认为您不能使用这些方法来进行程序集扫描;您需要单独注册验证器。

按名称

builder.RegisterType<EmployeeViewModelValidator>().Named<IValidator>("employee");

var r = container.Resolve<IValidator>("employee");

按键

文档显示了用作键的枚举,但您可以使用类型作为键,这样您就可以调用 Resolve 使用在 CreateInstance 方法中传递给您的 validatorType

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModelValidator));    

var r = container.Resolve<IValidator>(validatorType);

注意:该文档适用于 Autofac 2.3 版本。我使用的是 2.2.4,这就是上面的方法名称与文档不同的原因。

希望这有帮助。

To resolve from multiple classes that implement IValidator, the autofac documentation shows a couple of techniques. I don't think you can use assembly scanning with these methods; you'll have register the validators individually.

By Name

builder.RegisterType<EmployeeViewModelValidator>().Named<IValidator>("employee");

var r = container.Resolve<IValidator>("employee");

By Key

The documentation shows an enumeration being used as a key, but you could use the type as the key, which would let you call Resolve using the validatorType being passed to you in the CreateInstance method.

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModelValidator));    

var r = container.Resolve<IValidator>(validatorType);

Note: The documentation is for version 2.3 of Autofac. I'm using 2.2.4, which is why the method names above vary from the documentation.

Hope this helps.

过潦 2024-10-04 08:50:03

@adrift 的另一个答案是一个很好的干净方法。只是添加一些注释,这也适用于 Autofac 自动提供的 IIndex 关系类型,例如:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators;

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

重要说明:不要使用IContainerProvider 和 ApplicationContainer — 而是使用上面的 IComponentContextIIndex。这将有助于防止生命周期问题(您的示例将验证器与应用程序而不是请求生命周期相关联。)

The other answer by @adrift is a nice clean approach. Just to add some notes, this also works with the IIndex<K,V> relationship type, which Autofac provides automatically, e.g.:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators;

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    }

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

Important note: don't use IContainerProvider and ApplicationContainer in a component—instead use IComponentContext or IIndex<K,V> as above. This will help prevent lifetime issues (your example associates validators with the application rather than the request lifetime.)

假装不在乎 2024-10-04 08:50:03

当前注册代码:

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModel));
builder.RegisterType<ValidatorFactory>().As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

当前 ValidatorFactory:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators; 

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    } 

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

CreateInstance 内出现相同错误:

请求的服务“FluentValidation.IValidator`1[.EmployeeViewModel] (FluentValidation.IValidator)”尚未注册。

Current Registration Code:

builder.RegisterType<EmployeeViewModelValidator>().Keyed<IValidator>(typeof(EmployeeViewModel));
builder.RegisterType<ValidatorFactory>().As<IValidatorFactory>();

_containerProvider = new ContainerProvider(builder.Build());

Current ValidatorFactory:

public class ValidatorFactory : ValidatorFactoryBase {
    readonly IIndex<Type, IValidator> _validators; 

    public ValidatorFactory(IIndex<Type, IValidator> validators) {
        _validators = validators;
    } 

    public override IValidator CreateInstance(Type validatorType) {
        return _validators[validatorType];
    }
}

Same error inside CreateInstance:

The requested service 'FluentValidation.IValidator`1[.EmployeeViewModel] (FluentValidation.IValidator)' has not been registered.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文