2011-12-07 5 views
5

Antecedentes

Para ayudar a mejorar mi comprensión de la COI y cómo usarlo, quiero crear un ejemplo de las tres técnicas de inyección COI: Constructor de la inyección del organismo, e inyección de interfaz sin tener que usar un marco de terceros. Creo que tengo un ejemplo básico de inyección de constructor, pero estoy luchando con setter y la inyección de interfaz.COI contenedor personalizado - necesidad de ayuda en 2/3 tipos

Mi pregunta

¿Cómo usted se acerca abordar interfaz de la escritura y la inyección de la moda desde el principio?

Aquí está mi opinión, hágamelo saber si estoy en el camino correcto.

inyección de interfaz:

  1. bucle a través de objetos resueltos mediante la inyección de constructor instancia, comprobar para ver lo que las interfaces se implementan en interfaceDependencyMap
  2. Definir una especie de interfaceDependencyMap asociar una interfaz a la aplicación.
  3. resolver la aplicación usando interfaceDependencyMap
  4. asignar la propiedad adecuada al objeto inicializado con la inyección de constructor

inyección Setter:

  1. bucle a través de objetos resueltos crea una instancia utilizando la inyección de constructor
  2. definir algunos tipo de setterInjectionMap
  3. Resuelva el parámetro esperado de MethodInfo usando las asignaciones constructor
  4. Llame al método setter que pasa en el objeto de parámetro resuelto

Esto es lo que tengo hasta ahora para la inyección de constructor

public class Program 
{ 
    static void Main(string[] args) 
    { 
     // 
     //instead of doing this: 
     // 
     //ICreditCard creditCard = new Visa(); 
     //var customer = new Customer(creditCard); 
     //customer.Charge(); 


     var resolver = new Resolver(); 

     //map the types in the container 
     resolver.Register<Customer, Customer>(); 
     resolver.Register<ICreditCard, Visa>(); 

     //because the customer constructor has an ICreditCard parameter 
     //our container will automatically instantiate it recursively 
     var customer = resolver.Resolve<Customer>(); 

     customer.Charge(); 

    } 
} 

public interface ICreditCard 
{ 
    string Charge(); 
} 

public class Visa : ICreditCard 
{ 
    public string Charge() 
    { 
     return "Charging Visa"; 
    } 
} 

public class MasterCard : ICreditCard 
{ 
    public string Charge() 
    { 
     return "Charging MasterCard"; 
    } 
} 

public class Customer 
{ 
    private readonly ICreditCard _creditCard; 

    public Customer(ICreditCard creditCard) 
    { 
     this._creditCard = creditCard; 
    } 

    public void Charge() 
    { 
     _creditCard.Charge(); 
    } 
} 


public class Resolver 
{ 
    private Dictionary<Type, Type> dependencyMap = new Dictionary<Type, Type>(); 

    public T Resolve<T>() 
    { 
     return (T) Resolve(typeof (T)); 
    } 

    private object Resolve(Type typeToResolve) 
    { 
     Type resolvedType = null; 

     try 
     { 
      resolvedType = dependencyMap[typeToResolve]; 
     } 
     catch 
     { 
      throw new Exception(string.Format("could not resolve type {0}", typeToResolve.FullName)); 
     } 

     var firstConstructor = resolvedType.GetConstructors().First(); 
     var constructorParameters = firstConstructor.GetParameters(); 
     if (constructorParameters.Count() == 0) 
      return Activator.CreateInstance(resolvedType); 

     IList<object> parameters = constructorParameters.Select(parameterToResolve => Resolve(parameterToResolve.ParameterType)).ToList(); 

     return firstConstructor.Invoke(parameters.ToArray()); 
    } 

    public void Register<TFrom, TTo>() 
    { 
     dependencyMap.Add(typeof (TFrom), typeof (TTo)); 
    } 
} 
+5

¿Y cuál es la pregunta? – svick

+0

¿Hay alguna manera de que pueda volver a abrir esto? –

+0

@EricRomanowski: Vea las razones a continuación sobre por qué se cerró la pregunta; Si puede abordar esos motivos en su pregunta, entonces otros pueden votar para que se reabra, suponiendo que sientan que cumple con los estándares para las preguntas sobre SO. – casperOne

Respuesta

3

Es este tipo de lo que estás buscando ?

class Container 
{ 
    class Registration 
    { 
     public Type RegistrationType; 
     public Func<Container, object> Resolver; 
    } 

    List<Registration> registrations = new List<Registration>(); 

    public object Resolve(Type type) 
    { 
     return registrations 
      .First(r => type.IsAssignableFrom(r.RegistrationType)) 
      .Resolver(this); 
    } 

    public T Resolve<T>() 
    { 
     return (T)Resolve(typeof(T)); 
    } 

    public void Register<T>(Func<Container, T> registration) where T : class 
    { 
     registrations.Add(new Registration() 
     { 
      RegistrationType = typeof(T), 
      Resolver = registration 
     }); 
    } 
} 

Uso:

interface IDependency 
{ 
    string GetName(); 
} 

class ConcreteDependency : IDependency 
{ 
    public string GetName() 
    { 
     return "Concrete Dependency"; 
    } 
} 

class ConstructorExample 
{ 
    readonly IDependency dependency; 

    public ConstructorExample(IDependency dependency) 
    { 
     this.dependency = dependency; 
    } 

    public string GetString() 
    { 
     return "Consumer of " + dependency.GetName(); 
    } 
} 

class SetterExample 
{ 
    public IDependency Dependency { get; set; } 

    public string GetString() 
    { 
     return "Consumer of " + Dependency.GetName(); 
    } 
} 

[TestMethod] 
public void MyTestMethod() 
{ 
    var container = new Container(); 
    container.Register<IDependency>(c => new ConcreteDependency()); 
    container.Register(c => new ConstructorExample(c.Resolve<IDependency>())); 
    container.Register(c => new SetterExample() { Dependency = c.Resolve<IDependency>() }); 

    var constructor = container.Resolve<ConstructorExample>(); 
    Assert.AreEqual("Consumer of Concrete Dependency", constructor.GetString()); 

    var setter = container.Resolve<SetterExample>(); 
    Assert.AreEqual("Consumer of Concrete Dependency", setter.GetString()); 
} 

Si desea obtener más avanzada, le recomiendo conseguir la fuente de cualquiera de estos: SimpleInjector, Autofac, Ninject, StructureMap.

+0

Muchas gracias. Estuve luchando los últimos tres días tratando de encontrar la forma de escribir los genéricos para la interfaz y el colocador (no estoy seguro si esa es la terminología correcta). –

Cuestiones relacionadas