2012-11-08 40 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容器重新发明轮子。

相关问题