2

Based on the answers in this question: Cyclic dependency with ninject and this questions: Ninject: give the parent instance to a child being resolved both of these say you can use two way property injection to resolve cyclic dependencies as long as you change the scope to not be the default Transient Scope. So I tried doing that, I've got a UserService and a GroupService that require each other (and please don't say change the classes or use a third class, etc.!). I've got a generic EntityServiceFactory that uses ninject like so:

public static class EntityServiceFactory
{
    public static TServiceClass GetService<TServiceClass>()
        where TServiceClass : class
    {
    IKernel kernel = new StandardKernel();
    return kernel.Get<TServiceClass>();
    }
}

And my services:

public class GroupService : EntityService<GroupRepository, Group, DbContext>
{
    public UserService _userService { private get; set; }


    public GroupService(GroupRepository repository, UserService userService) : base(repository)
    {
        userService._groupService = this;
    }

public class UserService : EntityService<UserRepository, User, DbContext>
{
    public GroupService _groupService { private get; set; }

    public UserService(UserRepository repository, GroupService groupService)
        : base(repository)
    {
        groupService._userService = this;
    }

Then as per the instructions in the answers to those questions add the following to my EntityServiceFactory:

kernel.Bind<GroupService>().ToSelf().InCallScope();
kernel.Bind<UserService>().ToSelf().InCallScope();

But I still get the Error:

A cyclical dependency was detected between the constructors of two services.

Am I doing the two way property injection correctly? How do I resolve this?

Community
  • 1
  • 1
SventoryMang
  • 10,275
  • 15
  • 70
  • 113
  • I dont know the answer, but that is a well formed question. +1. – n00b Jul 25 '13 at 19:51
  • 1
    I know you insist in us not nagging about your design, but could you explain why those two services need to depend on each other? – Steven Jul 26 '13 at 07:17
  • btw. the usage of your `EntityServiceFactory` smells like the Service Locator anti-pattern. You might want to read [this article](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) to verify if the use of this pattern could be problematic in your application. – Steven Jul 26 '13 at 07:20
  • Thanks for the article. The design can't change due to how our framework was built using auto-generated code. Also because of the inheritance chain of these classes and the use of generics, pulling out shared logic into a third class would not be possible without duplicating a ton of code that doesn't need to be duplicated. I came up with 3 solutions to this problem, this one being the easiest to implement while also breaking the least amount of "standards". – SventoryMang Jul 26 '13 at 14:47

1 Answers1

2

Welp, turns out I didn't understand the answers in the questions I linked. I didn't do anything like property injection at all, what I ended up doing was this:

Anytime there was a cyclic dependency I would remove one of the cyclic-inducing services from the constructor and replace it with this:

    private UserService _userService;
    private UserService UserService
    {
        get { return _userService ?? (_userService = EntityServiceFactory.GetService<UserService>()); }
    }

This actually ended up being extremely close to what property injection is (http://ninject.codeplex.com/wikipage?title=Injection%20Patterns). It's not as optimal as constructor injection, but still isn't a bad solution. I also could have done this (actual property injection):

    private UserService _userService;
    [Inject]
    private UserService UserService
    {
        get { return _userService; }
        set { _userService = value; }
    }

I just chose my way since it doesn't require my services have ninject specific code in case I ever changed my usage of it, but called EntityServiceFactory.GetService is essentially doing the same thing as the [Inject] attribute.

SventoryMang
  • 10,275
  • 15
  • 70
  • 113