2016-11-26 3 views
2

Voici ce que je voudrais faire:Est-il possible d'injecter dans une méthode explicitement implémentée en utilisant Ninject?

public interface IInject<in T> 
{ 
    [Inject] 
    void Inject(T reference); 
} 

private class Foo : IInject<Bar> 
{ 
    public Bar Bar { get; private set; } 

    void IInject<Bar>.Inject(Bar reference) 
    { 
     Bar = reference; 
    } 
} 

Mais rien ne s'injecté, seule façon que je suis arrivé au travail est avec l'attribut et la mise en œuvre implicite:

private class Foo : IInject<Bar> 
{ 
    public Bar Bar { get; private set; } 

    [Inject] 
    public void Inject(Bar reference) 
    { 
     Bar = reference; 
    } 
} 

Est-il possible de le faire il?

+0

Ce qui manque à la question est * pourquoi * vous voulez faire cela. L'injection de méthode n'est généralement pas une bonne idée car elle conduit à [Couplage temporel] (http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/). – Steven

+1

@Steven L'injection de membre agréé est désagréable. J'ai hérité d'un graphique velu qui n'est pas favorable à l'IoC en raison des cycles. Ce faisant, il est à espérer que temporaire tout en refactorisant le design à quelque chose de plus agréable. –

Répondre

2

Ninject ne se comporte pas comme cela par défaut. Vous devrez créer un sélecteur personnalisé. *

Étant donné vos types ce sélecteur présente le comportement que vous avez décrit,

class ExplicitSelector : Selector 
{ 
    public ExplicitSelector(
     IConstructorScorer constructorScorer, 
     IEnumerable<IInjectionHeuristic> injectionHeuristics) 
     : base(constructorScorer, injectionHeuristics) 
    { 
    } 

    public override IEnumerable<MethodInfo> SelectMethodsForInjection(Type type) 
    { 
     // Gets all implemented interface and grabs an InterfaceMapping. 
     var implementedInterfaces = type.GetInterfaces(); 

     foreach (var map in implementedInterfaces.Select(type.GetInterfaceMap)) 
     { 
      for (var i = 0; i < map.InterfaceMethods.Length; i++) 
      { 
       // Check each interface method for the Inject attribute, and if present 
       if (map.InterfaceMethods[i].CustomAttributes.Any(x => x.AttributeType == typeof (InjectAttribute))) 
       { 
        // return the target method implementing the interface method. 
        yield return map.TargetMethods[i]; 
       } 
      } 
     } 

     // Defer to NInject's implementation for other bindings. 
     foreach (var mi in base.SelectMethodsForInjection(type)) 
     { 
      yield return mi; 
     } 
    } 
} 

Il est ajouté au noyau simplement,

standardKernel.Components.Remove<ISelector, Selector>(); 
standardKernel.Components.Add<ISelector, ExplicitSelector>(); 

Et puis les appels pour obtenir un IInject<Bar> fonctionneront comme vous le décrivez, en utilisant le sélecteur personnalisé.


* Il peut y avoir un meilleur point d'extension pour mettre en œuvre ce avec ninject. Je suis loin d'être un expert de NInject ou de sa mise en œuvre.