4

I have this class hierarchy:

public interface ISR { }
public interface ICU { }
public interface IFI { }   

public class CU : ICU { }

public class SR : ISR
{
    public SR(IFI fi)
    {
        FI = fi;
    }

    public IFI FI { get; set; }
}

public class FI : IFI
{
    public FI(ISR sr, ICU cu)
    {
        SR = sr;
        CU = cu;
    }

    public ISR SR { get; set; }
    public ICU CU { get; set; }
}

public class Module : NinjectModule
{
    public override void Load()
    {
        Bind<ISR>().To<SR>();
        Bind<ICU>().To<CU>();
        Bind<IFI>().To<FI>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var kernel = new StandardKernel(new Module());

        var sr = kernel.Get<ISR>();
    }
}

When I run this code, I have an exception because I have a cyclic dependency. The SR class needs an instance of IFI to be injected in order to be completed, and the FI class needs an instance of ISR to be injected.

Of course, using a property injection doesn't solve this issue.

I have a particularity though: I need ISR to be constructed first, and it is this instance which must be given to FI. So ISR and IFI need to share a scope.

How would you solve that with Ninject?

Steven
  • 166,672
  • 24
  • 332
  • 435
Emidee
  • 1,245
  • 1
  • 14
  • 33

1 Answers1

5

The best way to handle this problem is to refactor your design to remove the cyclic dependency. Almost all cyclic dependencies can be removed with a proper design. If you have cyclic dependencies there is usually a design flaw. Most likely you do not fulfill the Single Responsibility Principle.

Otherwise you have to do two way property injection and ensure they have the same scope. E.g. InCallScope from the NamedScope extension. See http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/

Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • I don't think I can refactor my classes. I've just tried to use a double property injection, and added .InCallScope() to the binding of IFI, but in this case, the constructor of SR is called, then the ctor of FI, and then the ctor of SR again, and finally I have a InvalidOperationException when I resolve ISR, with the message: Sequence contains no elements – Emidee May 31 '11 at 08:31
  • 2
    What makes it impossible to fix the cyclic dependency? I'd succest to read @Mark Seemann Book. It has an excellent chapter about how to fix cyclic dependencies. Anything else is just treat of symptoms. And two way property injection works very well just tested with InCallScope on both bindings. – Remo Gloor May 31 '11 at 10:36
  • IFI is a view-model used in composition by ISR (which is a view-model too) to display some infos. But IFI needs ISR to work, because it needs to access some properties of ISR, and to be notified when these properties are updated. BTW, I just tested the double property injection with InCallScope on both bindings (instead on only IFI binding) and I still have the exception. – Emidee May 31 '11 at 10:53
  • Sounds to me as if you are doing way too much in your view models. They should be kept as slim as possible. Consider to do some of the complicated work from outside of the view models. There you can easily have both of them as dependency. – Remo Gloor May 31 '11 at 22:44