2011-12-07 2 views
5

배경

에 도움이 필요가 그것을 사용하는 방법을, 나는 세 가지 IOC 기술의 예를 작성하려는 IOC의 나의 이해를 돕기 위해 타사 프레임 워크를 사용하지 않고도 인터페이스 주입이 가능합니다. 나는 constructor injection에 대한 기본적인 예제를 가지고 있다고 생각하지만, setter와 인터페이스 주입에 어려움을 겪고있다.사용자 정의 IOC 컨테이너 2/3 유형

내 질문

당신은 어떻게 처음부터 쓰기 인터페이스와 세터 주입을 다루는 방식 것인가?

내 생각은 여기에 있습니다. 내가 올바른 길을 가고 있는지 알려주세요.

인터페이스 주입 : 해결 객체를 통해

  1. 루프는 구현 인터페이스를 연결하는 interfaceDependencyMap의 일종을 정의
  2. interfaceDependencyMap
  3. 에서 구현되는 어떤 인터페이스를 확인, 생성자 주입을 사용하여 인스턴스화.
  4. 생성자 주입로 초기화 된 객체에 해당하는 속성을 할당 interfaceDependencyMap
  5. 을 사용하여 구현을 해결
세터 주입

: 해결 물체들

  1. 루프
  2. 일부 정의 생성자 주입하여 인스턴스화 일종의 setterInjectionMap
  3. 예상 매개 변수를 다음에서 해결하십시오. MethodInfo는
  4. 전화 해결 된 파라미터 객체 여기

전달 세터 방법을 생성자 매핑을 사용하면 내가 생성자 주입

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

그리고 무엇이 문제입니까? – svick

+0

다시 열 수있는 방법이 있습니까? –

+0

@EricRomanowski : 질문이 닫힌 이유에 대한 이유를 아래에서보십시오. 귀하가 귀하의 질문에 그러한 이유를 언급 할 수 있다면, 다른 사람들은 그것이 SO에 관한 질문의 기준을 충족한다고 생각할 때 재개되도록 투표 할 수 있습니다. – casperOne

답변

3

에 대해 지금까지 가지고있는 것은 당신이 찾고있는 무슨 이런 종류인가 ?

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 
     }); 
    } 
} 

사용법 :

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()); 
} 

더 고급 얻고 싶은 경우에, 나는이 중 어느 하나의 소스 점점 추천 : SimpleInjector, Autofac, Ninject, StructureMap을.

+0

정말 고마워. 나는 지난 3 일 동안 인터페이스와 세터에 대한 제네릭을 작성하는 방법을 알아 내려고 애썼다. (적절한 용어인지는 모르겠다.) –