Suggestion: make resolution order configurable

16 views
Skip to first unread message

TWischmeier

unread,
Nov 30, 2009, 7:26:04 AM11/30/09
to ninject-dev
Hi,

this is a suggestion for Ninject 2. By default, if multiple bindings
qualify for a specific resolution request, Ninject will select the
first one. This means you cannot overwrite / update bindings, beacuse
the first binding specific will always be resolved.

In my project I needed the ability to overwrite / update bindings so I
manually changed this behavior in the Ninject source code. The place I
am referring to are a couple of lines like this one:

public static T Get<T>(this IResolutionRoot root, params IParameter[]
{
return GetResolutionIterator(root, typeof(T), null, parameters,
false).Cast<T>().FirstOrDefault();
}

Those can be found in the Ninject.ResolutionExtensions - class. I know
I is not that easy to make a static class behavior configurable
without using some awkward code mechanics, but I thought there are
reasonable situations which would benefit from this option. Surely you
could always make those changes in the sourcecode yourself or write
your own ResolutionExtensions, but it would be cleaner if Ninject
already shipped with this option.

One possibility without resorting to a static option would be to add a
method like

T SelectFromEnumeration<T>(IEnumerable<T> resolutionIterator);

to the IResolutionRoot interface. You ould then change the Get<T>
methods in the ResolutionExtensions class to

public static T Get<T>(this IResolutionRoot root, params IParameter[]
{
return root.SelectFromenumeration(GetResolutionIterator(root,
typeof(T), null, parameters, false).Cast<T>());
}


Best regards,
Tim

Thedric Walker

unread,
Dec 10, 2009, 12:21:07 AM12/10/09
to ninject-dev
I may be missing something but it sounds like you could use the
Rebind<T> method to do what you have described.

TWischmeier

unread,
Dec 10, 2009, 4:21:54 AM12/10/09
to ninject-dev
Hi Thedric,

this has been one of my first ideas, but it does not work the way one
would expect. If you use Rebind(), it clears all bindings for that
service and then executes a standard Bind()-command. So if you have,
for example, the following bindings:

Bind<INavigationForm>().To<FormA>().Named("FormA");
Bind<INavigationForm>().To<FormB>().Named("FormB");

You then want to bind a different form to INavigationForm named FormB.
If you do

Rebind<INavigationForm>().To<FormBDifferent>().Named("FormB");

you will have no bindings for INavigationForm except FormBDifferent.
This ist not 100% intuitive because one might think that only the
binding which matches the arguments gets replaced.

That being said, I tried to modify Ninject2 to change the Rebind()
behavior, but it is far from trivial. To do a replace, you have to
wait until the binding command is complete, so doing it from the start
(like Rebind does) is not an option. So you'd have to add a command
like Instead() at the end of the command, but at that point you are in
the BindingBuilder where there's no way of deleting / overwriting /
altering bindings in the kernel.

So for me the only option was to modify the resolution behavior to
always resolve the latest binding added (this effects about 8 lines of
code in one class).

Surely, this may seem like a special case, but I do think that it
really is not at least in my case:
We have an application where you select one of several "wizards" -
basically use-cases with several steps. They do have a lot of
similarities, so I decided to make a hierarchy where you have an
abstract process from which all others inherit. It's basically a
module defining lots of bindings. And just like objects show
polymorphal behavior (because you can override methods, where the base
method assigns a value A to a field, and the overridinig method
replaces it with value B), I needed my bindings to be overridable (the
base method declares 20 bindings, and the overriding method replaces
some of them). I hope you know what I mean, describing complex
technical things in a foreign language is not the easiest thing to do.
Reply all
Reply to author
Forward
0 new messages