Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject: Passing client's assembly as constructor argument and specifying desired implementation from the client using attributes

I'm new to Ninject and Dependency Injection in general so please excuse my noobness here. =)

I have several implementations of an IConfig interface which scan an Assembly and its dependencies for types implementing an IConfigOption interface. Each IConfig implementation retrieves their values from different sources.

These implementations take the root Assembly from where to start scanning as a constructor argument, and I'm trying to come up with a binding that injects these values. So far I'm thinking of something in the lines of:

Bind<IConfig>().To<Config>().WithConstructorArgument("rootAssembly", target);

My problem is, I can't seem to find a way to get a reference to the target Assembly where the Config class would be injected. Without DI, I would use Assembly.GetCallingAssembly(), but in this context this yields the Assembly where the binding resides, and not the target one as desired.

Also, I need a way of specifying the intended implementation from the class/member that will receive the injection, so that for example, client class A asks for a Config implementor that uses RoleEnvironment and client class B asks for a Config implementor that uses ConfigurationManager. Here's an example to clarify the intended usage:

public class Client
{
    [UseApplicationConfig]
    public IHelper WithAppConfig { get; set; }

    [UseRoleEnvironmentConfig]
    public IHelper WithRoleEnvironmentConfig { get; set; }
}

public class Helper : IHelper
{
    public Helper(IConfig config)
    {
    }
}

I get the feeling that either I'm looking at this from the wrong angle or I'm missing the obvious, but i'm not sure what I should be looking for. How would be the best way to do it?

Thank you very much.

EDIT: Added an example of the intended usage and rephrased some parts of the question for clarity.

like image 500
Axel Magagnini Avatar asked Feb 01 '26 06:02

Axel Magagnini


1 Answers

If you want to get details about the request that's being made to the object, use the overload WithConstructorArgument(string, Func<IContext, object>). You can use the supplied IContext to look for the assembly name (use the debugger to look around, it sounds like your layout might be quite complex so I can't offer specific code).

As an example of how to use this:

//get the full name of the requested object
Bind<IFoo>()
    .To<Foo>()
    .WithConstructorArgument("bar",
                             c => c.Request.FullName);

However, it sounds to me like you're looking at it from the wrong angle. If I read your question correctly, it sounds like you have a class that scans your assemblies and then decides what to inject instead of letting Ninject do it for you. I assume this is a leftover from when you weren't using DI?

I'd take a look at using contextual binding with the WhenInjectedInto method or custom attributes to inject the specific IHelper that you want into the constructor. See here: https://github.com/ninject/ninject/wiki/Contextual-Binding

The linked page actually has an example of doing something similar that may work for you:

Bind<IWarrior>()
    .To<Samurai>()
    .When(request => request.Target.Type.Namespace.StartsWith("Samurais.Climbing"));

I'd probably still use WhenInjectedInto or attributes though so you don't have any "magic strings" in case you refactor your namespaces later.

like image 120
Adam Rodger Avatar answered Feb 03 '26 19:02

Adam Rodger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!