开发者

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 Weap开发者_运维问答on { 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


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.


I would recommend using an abstract factory that can create ISwords. This has an advantage over DependencyResolver in that the types it can create are bounded (to being ISword).

Your abstract factory/ies will need to be public, just like your DependencyResolver.


This doesn't directly answer your question, but I know with Unity, you can do this by using the Config files as opposed to wiring your dependencies in code. Ninject unfortunately doesn't have support for Config files.

Your alternative to this, is to use the non-generic overloads:

Bind(typeof(IWeapon)).To(typeof(Sword));

And then you should be able to do something like:

Bind(typeof(IWeapon)).To(Type.GetType("MyNamespace.MyInternalSword"))

but that's a big fugly if you ask me....

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜