在两个服务的构造函数之间检测到周期性依赖性

时间:2014-07-19 15:35:35

标签: c# asp.net asp.net-mvc ninject ninject.web.mvc

我正在使用最新的MVC框架,C#,.NET Framework 4.5.1和Ninject(最新版本)开发ASP.NET MVC Web API应用程序。我正在使用Visual Studio 2013 Ultimate,IIS Express和Windows 8.1 64位进行开发。

我收到了这个错误:

尝试创建UsersController类型的控制器时出错。确保控制器具有无参数的公共构造函数。

当我做http://mymachine:11156/api/users时。

这是我的NinjectConfigurator课程。

public class NinjectConfigurator
{
    public void Configure(IKernel container)
    {
        AddBindings(container);

        var resolver = new NinjectDependencyResolver(container);
        GlobalConfiguration.Configuration.DependencyResolver = resolver;
    }

    private void AddBindings(IKernel container)
    {
        ConfigureLog4net(container);

        // Unit of work.
        container.Bind<IUnitOfWork>().To<EFDbContext>().InRequestScope();

        // Repositories.
        container.Bind<IGenericRepository<User>>().To<GenericRepository<User>>();
        container.Bind<IGenericRepository<Group>>().To<GenericRepository<Group>>();
        container.Bind<IGenericRepository<Message>>().To<GenericRepository<Message>>();

        // Fetchers.
        container.Bind<IHttpUserFetcher>().To<HttpUserFetcher>();

        // Mappers.
        container.Bind<IGroupMapper>().To<GroupMapper>();
        container.Bind<IMessageMapper>().To<MessageMapper>();
        container.Bind<IUserMapper>().To<UserMapper>();
    }

    private void ConfigureLog4net(IKernel container)
    {
        log4net.Config.XmlConfigurator.Configure();
        var loggerForWebSite = LogManager.GetLogger("MattSocialNetworkWebApi");
        container.Bind<ILog>().ToConstant(loggerForWebSite);
    }
}

这些是地图制作者:

public class UserMapper : IUserMapper
{
    private readonly GroupMapper groupMapper;
    private readonly MessageMapper messageMapper;

    public UserMapper(GroupMapper groupMapper, MessageMapper messageMapper)
    {
        this.groupMapper = groupMapper;
        this.messageMapper = messageMapper;
    }

    [ ... ]
}

public class UserMapper : IUserMapper
{   
    public GroupMapper(IUserMapper userMapper, IMessageMapper messageMapper)
    {
        this.userMapper = userMapper;
        this.messageMapper = messageMapper;
    }

    [ ... ]
}

public class MessageMapper : IMessageMapper
{
    private readonly GroupMapper groupMapper;
    private readonly UserMapper userMapper;

    public MessageMapper(GroupMapper groupMapper, UserMapper userMapper)
    {
        this.groupMapper = groupMapper;
        this.userMapper = userMapper;
    }

    [ ... ]
}

这是我遇到问题的控制器:

public class UsersController : ApiController
{
    private IGenericRepository<Data.Models.User> userRepository;
    private IHttpUserFetcher httpUserFetcher;
    private IUserMapper userMapper;

    public UsersController(
        IGenericRepository<Data.Models.User> userRepository,
        IHttpUserFetcher httpUserFetcher,
        IUserMapper userMapper)
    {
        this.userRepository = userRepository;
        this.httpUserFetcher = httpUserFetcher;
        this.userMapper = userMapper;
    }

    [ ... ]
}

如果我从IUserMapper userMapper构造函数中删除UsersController参数,则可以正常工作。

你知道为什么我会收到这个错误吗?

更新

我收到此异常消息:

Error activating GroupMapper using implicit self-binding of GroupMapper
A cyclical dependency was detected between the constructors of two services.

Activation path:
  5) Injection of dependency GroupMapper into parameter groupMapper of constructor of type UserMapper
  4) Injection of dependency UserMapper into parameter userMapper of constructor of type GroupMapper
  3) Injection of dependency GroupMapper into parameter groupMapper of constructor of type UserMapper
  2) Injection of dependency IUserMapper into parameter userMapper of constructor of type UsersController
  1) Request for UsersController

Suggestions:
  1) Ensure that you have not declared a dependency for GroupMapper on any implementations of the service.
  2) Consider combining the services into a single one to remove the cycle.
  3) Use property injection instead of constructor injection, and implement IInitializable
     if you need initialization logic to be run after property values have been injected.

1 个答案:

答案 0 :(得分:1)

对于WebApi 2,您只需安装Ninject Web Host for WebApi 2即可。然后它将创建NinjectWebCommon。

enter image description here

这是一个例子 -

NinjectWebCommon

public static class NinjectWebCommon 
{
    ...
    private static IKernel CreateKernel()
    {
       ...
    }

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IUserService>().To<UserService>().InRequestScope();
    }        
}

控制器

public class UsersController : ApiController
{
    private readonly IUserService _userService;

    public UsersController(IUserService userService)
    {
        _userService = userService;
    }

    // GET: api/Users
    public IEnumerable<string> Get()
    {
        return _userService.GetUsers();
    }
}

服务

public interface IUserService
{
    string[] GetUsers();
}

public class UserService : IUserService
{
    public string[] GetUsers()
    {
        return new string[] { "value1", "value2" };
    }
}

注意:在绑定所有服务类之前先创建一个示例应用程序。否则,您将无法弄清楚哪个服务类忘记绑定。