Autofac中的异常:没有为此对象定义无参数构造函数

时间:2017-08-23 15:47:06

标签: c# .net asp.net-mvc-4 dependency-injection autofac

这是我的类,其中依赖项已解决

namespace TestProj
{
    public static class Bootstrapper
    {
        public static void Run()
        {
            SetAutofacWebAPI();
        }

        private static void SetAutofacWebAPI()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<UserService>().As<IUserService>().InstancePerRequest();
            builder.RegisterType<Encryption>().As<IEncryption>().InstancePerRequest();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(builder.Build()));
        }
    }
}

在Global.asax中,我有:Bootstrapper.Run();

这是我的UserService类:

public class UserService : IUserService
{
    private readonly IEncryption _Encryption;

    public UserService(Encryption Encryption)
    {
        _Encryption = Encryption;
    }
    //Rest of the service here
}

Encryption类是类似的。

控制器在这里:

public class UserController : Controller
{
    private readonly IUserService _UserService;
    public AccountController(UserService UserService)
    {
        _UserService = UserService;
    }

    public JsonResult GetLoginLogs(int Id)
    {
        var Logs = _UserService.GetLoginLogById(Id);
        return Json(Logs, JsonRequestBehavior.AllowGet);
    }
    //The rest of the controller
}

这是版本信息:

Autofac : 3.5.2
MVC : 4.0.40804.0
DOTNET : 4

然后,当尝试localhost:5000/Account/GetLoginLogs/1出现此异常时:

  

没有为此对象定义无参数构造函数。

有人请帮忙。我遇到了麻烦!

2 个答案:

答案 0 :(得分:3)

我认为您对注册依赖项的方式感到困惑。

@Amy的评论更新:

  

您也未能注册MVC控制器

// You can register controllers all at once using assembly scanning...
builder.RegisterControllers(Assembly.GetExecutingAssembly());

来源:documentation

当明确地注入依赖类时,也使用接口而不是具体类,就像你在容器中注册的一样。

public class UserService : IUserService {
    private readonly IEncryption _Encryption;

    public UserService(IEncryption Encryption) {
        _Encryption = Encryption;
    }
    //Rest of the service here
}

public class UserController : Controller {
    private readonly IUserService _UserService;

    public AccountController(IUserService UserService) {
        _UserService = UserService;
    }

    public JsonResult GetLoginLogs(int Id) {
        var Logs = _UserService.GetLoginLogById(Id);
        return Json(Logs, JsonRequestBehavior.AllowGet);
    }
    //The rest of the controller
}

答案 1 :(得分:1)

实际上,如果你深入研究并分析异常消息和堆栈跟踪,我相信你得到的异常并不会产生误导。您可以确切地找到容器无法找到和创建的服务 - 在这种情况下,UserService中的AccountController(以及Encryption中的UserService也是builder.RegisterType<UserService>() )。 &#34;没有找到无参数构造函数的例外&#34;简单地说,在现有的带参数的构造函数中,有一个或多个参数无法通过容器解析,并且由于缺少无参数构造函数,因此无法创建所需的类型。

这也可能意味着您忘记在容器中注册您的控制器,因此Autofac不知道它应该将任何依赖注入控制器。

更进一步 - Autofac对注册非常明确 - 您只能注入/解决您在应用程序启动时注册的内容。 如果您只使用As<> - 没有任何UserService,则只能直接注入.As<>。但是当您添加builder.RegisterType<UserService>().As<IUserService>()UserService时,您不能再注入IUserService,而是UserService。为了保留注入AsSelf()的可能性,您必须使用builder.RegisterType<UserService>().As<IUserService>().AsSelf()IUserService。然后,您可以同时注入UserServiceAs<>。请记住,Autofac注册API很流畅,您可以根据需要修改IUserService个。{/ p>

在Dependecy Injection世界中,我们不喜欢整合耦合的组件,因此不推荐注入具体类而不是接口 - 就像你所做的那样 - 你应该尽可能使用接口。因此,您的注册是正确的,但您应该在组件中注入UserService而不是IEncryptionEncryption而不是builder.RegisterControllers(Assembly.GetExecutingAssembly())‌​; 。 它可以简化这些组件的潜在单元测试,使您可以轻松地模拟依赖项。

此外,您还应注册您的控制器:

subprocess.run('i=0; while [ $i -lt 3 ]; do i=`expr $i + 1`; echo $i; done', shell=True)