Ninject get target type from IBinding
Asked Answered
K

3

6

I have an Interface that is implemented by several types. But before I do a kernel.GetAll<IAmServiceable>() I want to be able to ponder the target types of the injection.

I know the function kernel.GetBindings(typeof(IAmServiceable)) exists but this returns a list of IBinding's.

Does anyone know how I can get the target type from the IBinding?

I want to know the type that is bound to IAmServiceable before it gets instantiated.

Kellby answered 20/4, 2012 at 8:51 Comment(2)
Have you looked at using reflection to achieve the same thing? I'm not certain, but I think you can use it to find implemenations of a given interface within an assembly ...Adroit
Yes I did try that but it wont find a specific implementation of a generic class. GenericHostRunner<T> : IAmServicable which is bound in Ninject like: Bind<IAmServiceable>().To<GenericHostRunner<WCFHost>>() With reflection I'll only find GenericHostRunner.Kellby
O
3

This is not possible. E.g what is the type In this case?

Bind<IX>().ToMethod(c => RandomBool() ? new Foo() : new Bar());
Ontine answered 20/4, 2012 at 9:2 Comment(2)
But I just use Bind<IX>().To<Impl>(). :( Damn I was really hoping for a different answer.Kellby
I mean, I see that maybe this information isn't useful, but wouldn't the type be Func<IContext, IX>?Mullah
S
14

I know it's probably a bit late now for your problem, but since i ran into this today, i thought others might too.

That's the code i finally came up with - i don't think its perfect (far from it), especially regarding performance, but it works for my case, and since i do not intend to call this method very often, it seems ok to me.

public Type GetBoundToType(IKernel kernel, Type boundType)
{
    var binding = kernel.GetBindings(boundType).FirstOrDefault();
    if (binding != null)
    {
        if (binding.Target != BindingTarget.Type && binding.Target != BindingTarget.Self)
        {
            // TODO: maybe the code  below could work for other BindingTarget values, too, feelfree to try
            throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to, because it is bound using a method, provider or constant ", boundType));
        }

        var req = kernel.CreateRequest(boundType, metadata => true, new IParameter[0], true, false);
        var cache = kernel.Components.Get<ICache>();
        var planner = kernel.Components.Get<IPlanner>();
        var pipeline = kernel.Components.Get<IPipeline>();
        var provider = binding.GetProvider(new Context(kernel, req, binding, cache, planner, pipeline));
        return provider.Type;
    }

    if (boundType.IsClass && !boundType.IsAbstract)
    {
        return boundType;
    }
    throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to", boundType));
}
Stultify answered 14/11, 2013 at 14:16 Comment(0)
O
3

This is not possible. E.g what is the type In this case?

Bind<IX>().ToMethod(c => RandomBool() ? new Foo() : new Bar());
Ontine answered 20/4, 2012 at 9:2 Comment(2)
But I just use Bind<IX>().To<Impl>(). :( Damn I was really hoping for a different answer.Kellby
I mean, I see that maybe this information isn't useful, but wouldn't the type be Func<IContext, IX>?Mullah
B
0

If you are working within a NinjectModule (or have access to an IKernel some other way) A nice simple approach would be:

var concreteType = Kernel.Get<InterfaceType>().GetType();

Obviously, the downside is you create an instance of the concrete type. It is nevertheless nice and simple and I think pretty robust. Obviously, if the interface derives from IDisposable you would use a using statement:

using(var obj = Kernel.Get<InterfaceType>())
{
    var concreteType = obj.GetType();
    .
    .
    .
}
Bucksaw answered 11/7, 2018 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.