与Autofac集成时,C#ASP.Net核心面临问题

时间:2018-01-30 19:01:32

标签: c# dependency-injection autofac asp.net-core-1.1

我有一个控制器DailyExpenseController,我正在将IQueryExecutor类注入控制器。

DailyExpenseController

using HomeBudgetTrackingSystem.CrossCutting;
using HomeBudgetTrackingSystem.DTO;
using HomeBudgetTrackingSystem.Models;
using HomeBudgetTrackingSystem.Query;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace HomeBudgetTrackingSystem.Controllers
{
    [Produces("application/json")]
    [Route("api/DailyExpense/{Id}")]
    public class DailyExpenseController : Controller
    {
        private readonly IQueryExecutor queryExecutor;

        public DailyExpenseController(IQueryExecutor queryExecutor)
        {
            this.queryExecutor = queryExecutor;
        }

        [HttpPost]
        [Route("Create")]
        public async Task<IActionResult> CreateExpense(long Id, [FromBody] Expenditure expenditure)
        {
            var findEntity = new FindEntityQuery<Expense>(Id);
            var find = queryExecutor.Execute(findEntity);

            /*if (find == null)
                return NotFound();*/


            var createExpenses = new CreateExpenditure(expenditure);
            var expenses = queryExecutor.Execute(createExpenses);
            return Ok(expenses);
        }

        /*If I write this method, it will result in 500 Error, because this method has id which is confusing 
         with the variable Id declared with Controller*/
        /*[HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }*/

        [HttpGet("{id2}")]
        public string Get(long id)
        {
            return "value";
        }

        [HttpPost]
        public void Post([FromBody]string value)
        {
        }

    }
}

以下是我的Autofac配置详情

Startup.cs

using Autofac;
using Autofac.Extensions.DependencyInjection;
using HomeBudgetTrackingSystem.Repository;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace HomeBudgetTrackingSystem
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        //public void ConfigureServices(IServiceCollection services)
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            /*services.AddDbContext<BudgetContext>(options =>
             options.UseSqlServer(Configuration.GetConnectionString("BudgetConnection")
        )); */

            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.RegisterModule(new RepositoryHandlerModule());
            //builder.RegisterType<QueryExecutor>().As<IQueryExecutor>();
            ApplicationContainer = builder.Build();
            return new AutofacServiceProvider(ApplicationContainer);
        }

        public IContainer ApplicationContainer { get; private set; }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
            appLifetime.ApplicationStopped.Register(() => ApplicationContainer.Dispose());
        }
    }
}

下面是我的模型构建器类,我在其中注册了依赖项

RepositoryHandlerModule.cs

using Autofac;
using HomeBudgetTrackingSystem.CrossCutting;

namespace HomeBudgetTrackingSystem.Repository
{
    public class RepositoryHandlerModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<QueryExecutor>().As<IQueryExecutor>().InstancePerRequest();
        }
    }
}

我没有对Program.cs进行任何更改

Program.cs的

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace HomeBudgetTrackingSystem
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

以下是我收到的例外情况

  

Autofac.Core.DependencyResolutionException:无法解析类型&#39; HomeBudgetTrackingSystem.CrossCutting.QueryExecutor&#39;因为它所属的生命范围无法找到。此注册公开了以下服务:    - HomeBudgetTrackingSystem.CrossCutting.IQueryExecutor

     

详情---&gt;没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围可见。

     

如果在执行Web应用程序期间看到此情况,则通常表示SingleInstance()组件(或类似方案)正在请求按HTTP请求注册的组件。在Web集成下,始终从依赖项解析程序或请求生存期范围请求依赖项,而不是从容器本身请求。 (详见内部异常。)---&gt; Autofac.Core.DependencyResolutionException:没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围可见。

     

如果在执行Web应用程序期间看到此情况,则通常表示SingleInstance()组件(或类似方案)正在请求按HTTP请求注册的组件。在Web集成下,始终从依赖项解析程序或请求生存期范围请求依赖项,而不是从容器本身请求。      在Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope)      在Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration注册,IResolveOperation上下文,ISharingLifetimeScope mostNestedVisibleScope,IEnumerable 1 parameters) --- End of inner exception stack trace --- at Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable 1个参数)      at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope,IComponentRegistration registration,IEnumerable 1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable 1个参数)      at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context,Service service,IEnumerable 1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable 1个参数)      在Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp,Type type,Type requiredBy,Boolean isDefaultParameterRequired)      在lambda_method(Closure,IServiceProvider,Object [])      在Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider。&lt;&gt; c__DisplayClass4_0.b__0(ControllerContext controllerContext)      在Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider。&lt;&gt; c__DisplayClass5_0.g__CreateController | 0(ControllerContext controllerContext)      在Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State&amp; next,Scope&amp; scope,Object&amp; state,Boolean&amp; isCompleted)      在Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()      在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)      在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()      在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)      在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State&amp; next,Scope&amp; scope,Object&amp; state,Boolean&amp; isCompleted)      在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()      在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)      在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()      在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)      在Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()      在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)      在Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()

我已经在这些上提到了多个链接。突出的是

http://autofac.readthedocs.io/en/latest/faq/per-request-scope.html http://autofac.readthedocs.io/en/latest/integration/aspnetcore.html (我更喜欢没有容器的配置) http://www.codedigest.com/posts/49/using-autofac-instead-of-inbuilt-di-container-with-in-aspnet-core-mvc(这是我提到的那个)

有人可以帮我解决这些问题吗?

1 个答案:

答案 0 :(得分:1)

我能够找到问题的解决方案。

http://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html

此处标题&#39;与ASP.NET Classic的区别&#39;列出了一个关键点 使用InstancePerLifetimeScope而不是InstancePerRequest。

我还在RepositoryHandlerModule.cs中进行了更改,例如添加BudgetContext.cs 如下所示

public class RepositoryHandlerModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);
            builder.RegisterType<QueryExecutor>().As<IQueryExecutor>().InstancePerLifetimeScope();
            builder.RegisterType<BudgetContext>().InstancePerLifetimeScope();
        }
    }