我正在尝试使用 Autofac 将依赖项注入(inject)到 MVC 4 应用程序中的 FluentValidation 中。我想我已经制定了策略,但是我一直无法解决我的单例请求 ISomething。
这是场景:
我有一个从 FluentValidation 的 AbstractValidator 派生的验证器。我读过 FluentValidation 验证器作为单例执行得最好,所以我的构造函数需要一个 Func 并存储该 Factory 以供以后使用。使用验证器时,它应该向存储的工厂请求 IDataStore,获取为该请求创建的实例并使用它。这就是理论。我想感谢 https://github.com/robdmoore/UnobtrusiveMVCTechniques ,这帮助我解决了这个解决方案。这是验证器...
public class SiteAdminViewModelValidator : AbstractValidator<SiteAdminViewModel> {
private readonly Func<IDataStore> _dbFactory;
public SiteAdminViewModelValidator(Func<IDataStore> dbFactory) {
_dbFactory = dbFactory;
RuleFor(model => model.SiteCode).Length(1, 40).Must(BeSpecial);
}
public bool BeSpecial(string siteCode) {
var db = _dbFactory();
List<Stuff> stuffs = db.All<Stuff>().ToList();
return true;
}
}
如果有人可以为我指出我正在尝试完成的工作示例,那就太好了,但我也想知道解决这个特定的 Autofac 技巧的方法。
这是我的验证人注册...
public class FluentValidatorModule : Module {
protected override void Load(ContainerBuilder builder) {
base.Load(builder);
builder.RegisterType<AutofacValidatorFactory>().As<IValidatorFactory>().SingleInstance();
var validators = AssemblyScanner.FindValidatorsInAssembly(System.Reflection.Assembly.GetExecutingAssembly());
validators.ToList().ForEach(v => builder.RegisterType(v.ValidatorType).As(v.InterfaceType).SingleInstance());
}
}
这是我对 IDataStore 工厂的注册...
builder.RegisterType<SuperDB>().As<IDataStore>().InstancePerHttpRequest();
builder.Register<Func<IDataStore>>(c => {
var context = c.Resolve<IComponentContext>();
return context.Resolve<IDataStore>;
});
这是我的验证器在线请求 IDataStore 时遇到的错误 -
var db = _dbFactory();
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
...这正是我在编写自己的工厂注册之前尝试它时得到的——Func 注册。通过阅读类似问题的各种答案,看起来我上面的内容应该可以工作,因为我认为我现在正在解析 Func 以获得当前的解析器。
任何帮助将不胜感激。
最佳答案
我同意这应该可行 - Func<IDataStore>
正在定义一个工厂,它将根据需要在每个方法中生成依赖项。
我绕过这种方法的方法是使用 DependencyResolver.Current
就像错误消息所暗示的那样。主要原因是我已经使用 Autofac.Mvc4 nuget 包进行了设置...
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
所以要实际设置方法,我有以下功能
public Func<T> PerHttpSafeResolve<T>()
{
return () => DependencyResolver.Current.GetService<T>();
}
并且在构建容器时
builder.RegisterType<SuperDB>().As<IDataStore>().InstancePerHttpRequest();
builder.RegisterInstance(PerHttpSafeResolve<IDataStore>());
编辑:注册实例的第二行是 - 如果您需要
Func<IDataStore>
然后使用传递给方法的值。 PerHttpSafeResolve<IDataStore>
的结果只是一个函数(工厂),因此它可以作为单个实例存在。
关于inversion-of-control - Autofac - 如何从单例中解析 ISomething 的 Func,其中 ISomething 是 InstancePerHttpRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15538665/