inversion-of-control - Autofac - 如何从单例中解析 ISomething 的 Func,其中 ISomething 是 InstancePerHttpRequest

标签 inversion-of-control autofac fluentvalidation

我正在尝试使用 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/

相关文章:

entity-framework - EF Code First、IoC 和 DbConnection

c# - 找出哪个模块注册了类型

silverlight - 将结构图转换为 Autofac

c# - 使用 Autofac 注册部分封闭的泛型

c# - FluentValidation 正在请求 IValidator<string>

asp.net-mvc - Fluent 验证 When 子句

c++ - 通过构造函数进行依赖注入(inject)的最佳实践

c# - 如何在不创建循环引用的情况下在多项目解决方案中使用 SimpleInjector

servicestack - 拦截 Fluent 验证

c# - 如何在数据层使用 Caliburn.Micro SimpleContainer