Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Ninject, can I create an instance from an interface without exposing my concrete class?

The samples I've seen so far look like this:

Write your code like this...

public class Samurai {
  public IWeapon Weapon { get; private set; }
  public Samurai(IWeapon weapon) {
    Weapon = weapon;
  }
}

And Ninject can map the interface to the concrete type like this...

public class WarriorModule : NinjectModule {
  public override void Load() {
    Bind<IWeapon>().To<Sword>();
  }
}

So when I say var samurai = kernel.Get<Samurai>(); in my Samurai object my IWeapon is automatically a Sword.

That's cool, but what if I want just the ISword without the Samurai and the concrete sword is marked as internal?

Currently, I use a home made dependency resolver where I could say var sword = DependencyResolver.Current.Resolve<ISword>(); and it gives me back a Sword cast as ISword. My concrete classes are marked as internal so the developer must go through my dependency resolver to create an instance. Does Ninject have anything similar to this?

And a bonus question, I decorate my Interfaces with a custom "DefaultConcreteType" attribute which my dependency resolver can use if no mapping exists. Does Ninject have anything like that either?

Thanks

like image 647
adam0101 Avatar asked Mar 15 '11 16:03

adam0101


1 Answers

When you bind an interface to a concrete type, you can ask for an instance of that interface and obtain the concrete type. In your example, you could do this:

var sword = kernel.Get<ISword>();

And this would give you a concrete Sword object. You can do a lot more with the binding system, too. You could even Bind<ISword>().ToMethod(MySwordFactory); and write a method to get Swords based on the requesting context.

Another thing you can do is to change how binding works based on the type it's being injected into. For example, you could expose a property on a custom class like so:

public class MyClass {
    [Inject]
    public ISword Sword { get; set; }
}

And then you could bind to a specific ISword implementation based on the MyClass:

Bind<ISword>().To<Sword>().WhenInjectedInto<MyClass>();

There are a lot more options, but this should give you a rough overview.

like image 115
Scott Anderson Avatar answered Sep 17 '22 15:09

Scott Anderson