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

不器用なコードなどで申し訳ありません。ここから始めましょう。

4

1 に答える 1

0

始めたばかりの場合、IOCコンテナをリバースエンジニアリングしようとすることは、実際に取り組むべきことではありません。提供されたコードを再実装し、いくつかの空白を埋めましたが、私が見ることができることから、コンテナーの要点が欠落しています。

class Mkontener: UnresolvedDependenciesException, IContainer

Mkontenerがコンテナクラスになる場合、基本クラスとしてカスタム例外のように見えるものを拡張するのはなぜですか?また、IContainerインターフェイスを実装しようとしています。これがComponentModelのIContainerである場合、クラスはコンパイルされません。独自のIContainerインターフェイスを作成した場合は、混乱や名前の競合を避けるために、より適切な名前を使用することをお勧めします。

IOCコンテナは、次のいずれかによって機能します。A)インターフェイスに対して具象型を登録する。(そして、インターフェースを要求されたときに具体的なタイプの新しいインスタンスをセットアップする方法をコンテナーに理解させ、スコープを管理します。つまり、要求ごとのシングルトンとインスタンス)B)インターフェースに対して具体的なインスタンスを登録します。(古典的なシングルトンの振る舞い)

あなたの実装はどちらもしていません。レジスタは、具象型とインタフェース型を受け入れる必要があります。Resolveは、使用するインターフェースを通知され、登録された具象型のインスタンスを構築(または返す)します。あなたが書き込もうとしているような単純な例は、動的インスタンスファクトリにすぎません。IoCコンテナの真の力は、オブジェクトが要求されたときにオブジェクトの依存関係を自動的に解決する方法を知っていることです。

たとえば、一致する実装を持つ次のインターフェイスがある場合:IRepository、ILoggingService、IDataService、IMessagingService、IAppController

各インターフェイスが、コンストラクターが次のように見える特定の具象タイプに登録されると、次のようになります。Repository(IDataService dataService、ILoggingService loggingService)
MessagingService(ILoggingService loggingService)
AppController(IRepository repository、IMessagingService MessagingService)

それぞれを登録すると、次のようになります。

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コンテナを使って車輪の再発明を試みさせるのはかなり奇妙だと思います。

于 2012-11-08T02:42:27.957 に答える