It binds UIRuleSetAccessor in constructor parameters to a singleton UIRuleSetAccessor instance, meaning, there will be only created one.
Ill try to explain on an example.
Your system looks like this:
You have soem classes A B C D, that are part of the system "frame", you will only ever need one of each. The following constuctors apply:
A()
B(A a)
C(A a)
D(A a,B b)
Then you have some dynamic parts of the system E F G, that are needed for each Foobar the system handles (how many of which tehre are, you can only tell in runtime)
Following constructors apply:
E(A a,F f, G g)
F()
G(F f)
Where the two f-s shuold be the same instance
HOw would yuo design the build of such a system? Clearly, A B C and D should be singletons, while E F and G are not. One of the cleverer apporach is to create a "System builder" class, that creates all instances as necessary, so in the class itself, you dont have to worry about system building. However, if you make a lot of projects, you will eventually distill a reusable system builder class, that you can parametrize for the given project. Then, if that is done, you will want to pack it into a neat package and sell/give it to others. This is basically how most DI frameworks happen, including Ninject.
There is a plethora of ways how parametrization can happen (XML, annotations or constructor params are a few possibilities) We use constructor parameters, which has a few drawbacks ( that we can avoid by not using static instances of basically anything that needs injection) The Binding rules give the needed context for Ninject to properly build things. (Ideally, all things would be created by this, but I found it easier to include a factory class or two as well)
We mostly use Bind<X>.ToSelf(). This tells Ninject to just make a new instance of X whenever he wants to create something with a constuctor that needs X.
Bind<Y>.ToSelf().InSingletonScope() makes it so Y is a singleton, an that singleton is used whenever Y is a ctor param.
Screens are special: we bind multiple implementors to the Screen interface (or is it a base class? whatever) in effect creating a list of screens.
NEQueue is also special: we have 2 named instances, the "in" queue and the "out" queue, whenever we need a NEQueue in a ctor, we have to specify which one we want. (with the help of an attribute on the parameter, you can see how this works in the MainLogic class)
There are some other possibilities, so if these dont cover your usecase, you need to read the docs.
To finish our example:
Bind<A>().ToSelf().InSingletonScope();
Bind<B>().ToSelf().InSingletonScope();
Bind<C>().ToSelf().InSingletonScope();
Bind<D>().ToSelf().InSingletonScope();
Bind<E>().ToSelf();
Bind<F>().ToSelf().InCallScope();
Bind<G>().ToSelf();
Then you do
...
var kernel=new StandardKernel(context);
A main=kernel.Get<A>();
...
and whenewer a FooBar is oincoming
...
void handleFoobarIncoming()
{
Elist.Add(kernel.Get<E>())
}
This is a very basic rundown, but they have a very nice wiki, you can easily read up on everything there.
Ill try to explain on an example.
Your system looks like this:
You have soem classes A B C D, that are part of the system "frame", you will only ever need one of each. The following constuctors apply:
A()
B(A a)
C(A a)
D(A a,B b)
Then you have some dynamic parts of the system E F G, that are needed for each Foobar the system handles (how many of which tehre are, you can only tell in runtime)
Following constructors apply:
E(A a,F f, G g)
F()
G(F f)
Where the two f-s shuold be the same instance
HOw would yuo design the build of such a system? Clearly, A B C and D should be singletons, while E F and G are not. One of the cleverer apporach is to create a "System builder" class, that creates all instances as necessary, so in the class itself, you dont have to worry about system building. However, if you make a lot of projects, you will eventually distill a reusable system builder class, that you can parametrize for the given project. Then, if that is done, you will want to pack it into a neat package and sell/give it to others. This is basically how most DI frameworks happen, including Ninject.
There is a plethora of ways how parametrization can happen (XML, annotations or constructor params are a few possibilities) We use constructor parameters, which has a few drawbacks ( that we can avoid by not using static instances of basically anything that needs injection) The Binding rules give the needed context for Ninject to properly build things. (Ideally, all things would be created by this, but I found it easier to include a factory class or two as well)
We mostly use Bind<X>.ToSelf(). This tells Ninject to just make a new instance of X whenever he wants to create something with a constuctor that needs X.
Bind<Y>.ToSelf().InSingletonScope() makes it so Y is a singleton, an that singleton is used whenever Y is a ctor param.
Screens are special: we bind multiple implementors to the Screen interface (or is it a base class? whatever) in effect creating a list of screens.
NEQueue is also special: we have 2 named instances, the "in" queue and the "out" queue, whenever we need a NEQueue in a ctor, we have to specify which one we want. (with the help of an attribute on the parameter, you can see how this works in the MainLogic class)
There are some other possibilities, so if these dont cover your usecase, you need to read the docs.
To finish our example:
Bind<A>().ToSelf().InSingletonScope();
Bind<B>().ToSelf().InSingletonScope();
Bind<C>().ToSelf().InSingletonScope();
Bind<D>().ToSelf().InSingletonScope();
Bind<E>().ToSelf();
Bind<F>().ToSelf().InCallScope();
Bind<G>().ToSelf();
Then you do
...
var kernel=new StandardKernel(context);
A main=kernel.Get<A>();
...
and whenewer a FooBar is oincoming
...
void handleFoobarIncoming()
{
Elist.Add(kernel.Get<E>())
}
This is a very basic rundown, but they have a very nice wiki, you can easily read up on everything there.