Autofac-如何从Isomething为InstancePerHttpRequest的Singleton解析Func for ISomething [英] Autofac - how to resolve Func for ISomething from Singleton where ISomething is InstancePerHttpRequest

查看:94
本文介绍了Autofac-如何从Isomething为InstancePerHttpRequest的Singleton解析Func for ISomething的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Autofac在MVC 4应用程序中将依赖项注入FluentValidation.我认为我已经制定了策略,但是我无法解决单例的每个请求的ISomething.

I'm trying to use Autofac to inject dependencies into FluentValidation in an MVC 4 app. I think I've got the strategy worked out, but I'm getting stuck with resolving my per-request ISomething from a singleton.

这是场景: 我有一个从FluentValidation的AbstractValidator派生的验证器.我已经读过FluentValidation验证器以单例形式表现最佳,因此我的构造函数需要一个Func并将该Factory存储起来供以后使用.使用验证器时,应向存储的工厂询问IDataStore,获取为该请求创建的实例并使用它.那是理论.我想归功于 https://github.com/robdmoore/UnobtrusiveMVCTechniques ,它帮助我解决了这个问题.这是验证器...

Here's the scenario: I've got a validator that derives from FluentValidation's AbstractValidator. I've read that FluentValidation validators perform best as singletons, so my constructor expects a Func and stores that Factory for use later. When the validator is used, it should ask the stored factory for an IDataStore, get the instance created for that request and use it. That's the theory. I want to give credit to https://github.com/robdmoore/UnobtrusiveMVCTechniques, which helped me settle on this solution. Here's the validator...

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技巧的解决方案.

If someone can point me to a working example of what I'm trying to accomplish, that would be great, but I'd also like to know the solution to this particular piece of Autofac tricksyness.

这是我的验证者注册...

Here's my validator registration...

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工厂的注册...

Here's my registration for the IDataStore factory...

builder.RegisterType<SuperDB>().As<IDataStore>().InstancePerHttpRequest();
builder.Register<Func<IDataStore>>(c => {
                                       var context = c.Resolve<IComponentContext>();
                                       return context.Resolve<IDataStore>;
                                   });

这是当我的验证器在线请求IDataStore时遇到的错误- var db = _dbFactory();

Here's the error I'm getting when my validator asks for an IDataStore on the line - var db = _dbFactory();

在 请求实例的范围.这通常表明 由HTTP请求注册为HTTP请求的组件 Web下的SingleInstance()组件(或类似方案). 集成总是向 DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime, 永远不会来自容器本身.

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.

...这正是我在编写自己的Factory注册-Func注册之前尝试过的结果.通过阅读各种类似问题的答案,我上面的内容应该可以使用,因为我认为我现在正在解析Func以获得当前的解析器.

...which is exactly what I got when I tried it prior to writing my own Factory registration - the Func registration. From reading various answers to similar questions, it looked like what I have above should work because I thought I was now resolving the Func to get the current resolver.

任何帮助将不胜感激.

推荐答案

我同意这应该起作用-Func<IDataStore>定义了一个工厂,它将根据需要在每种方法中产生依赖关系.

I agree that this should work - the Func<IDataStore> is defining a factory that will produce the dependency in each method as required.

我绕过此方法的方法是使用DependencyResolver.Current,如错误消息所示.主要原因是我已经使用Autofac.Mvc4 nuget包对其进行了设置...

The way that I got around this method is to use the DependencyResolver.Current like the error message suggests. The main reason is that I already had it set up using the Autofac.Mvc4 nuget package...

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

所以要实际设置该方法,我需要以下功能

So to actually setup the method I have the following func

public Func<T> PerHttpSafeResolve<T>()
{
    return () => DependencyResolver.Current.GetService<T>();
} 

在构造容器时

builder.RegisterType<SuperDB>().As<IDataStore>().InstancePerHttpRequest();
builder.RegisterInstance(PerHttpSafeResolve<IDataStore>());

正在注册实例的第二行说-如果需要Func<IDataStore>,则使用传递到方法中的值. PerHttpSafeResolve<IDataStore>的结果只是一个函数(工厂),因此它可以作为单个实例存在.

The second line that is registering the instance is saying - If you need a Func<IDataStore> then use the value passed into the method. The result of the PerHttpSafeResolve<IDataStore> is just a function (factory), so it can live as a single instance.

这篇关于Autofac-如何从Isomething为InstancePerHttpRequest的Singleton解析Func for ISomething的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆