2012-11-08 41 views
1

我是一名學生,我的工作是建立自己的IoC容器。我已經閱讀了一些教程/代碼示例,並最終創建了它,但是當我嘗試創建它的實例時,我會在主題中獲得異常。這裏是我的IoC代碼和測試代碼,我一直在試圖弄清楚什麼是錯的,但是找不到它。由於對象的當前狀態,操作無效

的IoC

public class Mkontener: UnresolvedDependenciesException, IContainer 
{ 
    private readonly Dictionary<Type, object> container = new Dictionary<Type, object> { }; 

    public void Register(System.Reflection.Assembly assembly) 
    { 

     Type[] mytypes = assembly.GetTypes(); 


     foreach (Type t in mytypes) 
     { 
      if (!container.ContainsKey(t)) 
      { 
       container.Add(t, Activator.CreateInstance(t)); 
      } 
     } 
     //throw new NotImplementedException(); 
    } 

    public void Register(Type type) 
    { 
     if (!container.ContainsKey(type)) 
     { 
      container.Add(type, Activator.CreateInstance(type)); 
     } 
     //throw new NotImplementedException(); 
    } 

    public void Register(object impl) 
    { 
     Type t = impl.GetType(); 
     if (!container.ContainsKey(t)) 
     { 
      container.Add(t, impl); 
     } 

     // throw new NotImplementedException(); 
    } 

    public void Register<T>(Func<T> provider) where T : class 
    { 

     container.Add(provider.GetType(), provider); 
     //throw new NotImplementedException(); 
    } 

    public T Resolve<T>() where T : class 
    { 

     return (T)Resolve(typeof(T)); 
    } 

    public object Resolve(Type type) 
    { 
     List<ConstructorInfo> konstruktor = new List<ConstructorInfo> { }; 
     foreach (ConstructorInfo cons in type.GetConstructors()) 
     { 
      konstruktor.Add(cons); 
     } 
     if (konstruktor.Count == 0) 
     { 
      return Activator.CreateInstance(type); 
     } 
     else 
     { 
      ConstructorInfo active = null; 
      int lparams = 0; 
      foreach (ConstructorInfo cnst in konstruktor) 
      { 
       int inner=0; 
       foreach (ParameterInfo a in cnst.GetParameters()) 
       { 
        inner++; 
       } 
       if (inner > lparams) 
       { 
        active = cnst; 
       } 

      } 
      List<object> lista = new List<object> { }; 
      foreach(ParameterInfo param in active.GetParameters()) 
      { 
       if (container.ContainsKey(param.GetType())) 
       { 
        lista.Add(container[param.GetType()]); 
       } 
       else 
       { 
        //throw new UnresolvedDependenciesException(); 
       } 
      } 

      object[] obiekty= lista.ToArray(); 
      return Activator.CreateInstance(type, obiekty); 
     } 
     if (container.ContainsKey(type)) 
     { 
      return container[type]; 
     } 
     else 
     { 
      //throw new UnresolvedDependenciesException(); 
     } 

    } 


    public void Register<T>(T impl) where T : class 
    { 
     container.Add(impl.GetType(), impl); 
    } 
} 

部分測試單元

public void P1__Container_Should_Register_Singleton_As_Object() 
{ 
    // Arrange 
    var container = (IContainer)Activator.CreateInstance(LabDescriptor.Container); 
    var singleton = new FakeImpl(); 

    // Act 
    container.Register(singleton); 
    var result = container.Resolve<IFake>(); 

    // Assert 
    Assert.That(result, Is.Not.Null); 
    Assert.That(result, Is.SameAs(singleton)); 
} 

對不起,笨拙的代碼等等。剛開始在這裏的。

回答

0

如果您剛開始嘗試對IOC容器進行逆向工程,那麼您不應該嘗試着解決這個問題。我已經重新實現了您提供的代碼,填充了一些空白,但是從我所看到的您看不到容器的角度來看。

class Mkontener: UnresolvedDependenciesException, IContainer 

如果Mkontener將是你的容器類,它爲什麼延長看起來是一個自定義異常的基類?此外,您正在嘗試實施IContainer界面。如果這是ComponentModel的IContainer,那麼你的類將不會編譯。如果您已經創建了自己的IContainer接口,那麼我會建議使用更合適的名稱以避免混淆/命名衝突。

IOC容器的工作方式如下: A)根據接口註冊具體類型。 (並且讓容器在詢問接口時如何設置具體類型的新實例並管理作用域,即每個請求對應單實例還是實例)B)根據接口註冊具體實例。 (經典的單身行爲)

你的實現既不做也不做。註冊需要接受具體類型和接口類型。將會告訴Resolve將使用哪個接口,然後構造(或返回)已註冊具體類型的實例。像你想寫的簡單的例子不過是一個動態的實例工廠。 IoC容器的真正威力在於知道如何在請求時自動解析對象的依賴關係。

例如,給定I與實施方式以下接口以匹配: IRepository,ILoggingService,IDataService,IMessagingService,IAppController

一旦每個接口與一個給定的具體類型,其中構造看起來像註冊: 庫( IDataService的DataService,ILoggingService loggingService)
的MessagingService(ILoggingService loggingService)
的AppController(IRepository庫,IMessagingService的MessagingService)

註冊EAC^h看起來是這樣的:

MyContainer.Register<LoggingService>().As<ILoggingService>(); 
MyContainer.Register<DataService>().As<IDataService>(); 
MyContainer.Register<MessagingService>().As<IMessagingService>(); 
MyContainer.Register<Repository>().As<IRepository>(); 
MyContainer.Register<AppController>().As<IAppController>(); 

爲了得到一個應用程序控制器,我想只要致電:

var controller = MyContainer.Resolve<IAppController>(); 

容器數字如何構建IRepostory和IMessagingService和所有的依賴關係是基於已經註冊的。(如果它不能,拋出一個異常,希望能指出開發者沒有正確設置的東西。)

如果你想看看IOC容器裏面發生了什麼,看看Autofac。它是一個開源的容器,但是一個警告,在IOC容器內有很多複雜的代碼。我覺得很奇怪的是,課程將嘗試讓學生用IoC容器重新發明輪子。

相關問題