0

私は自分のIoCツールを手で転がそうとしています。

これはIoCコードの一部です。

public static object Resolve(Type contract)
{
   Type Implementation = typeSettings[contract];

   ConstructorInfo constructor = Implementation.GetConstructors()[0];

   ParameterInfo[] constructorParam = constructor.GetParameters();

   if (constructorParam.Length == 0)
      Activator.CreateInstance(Implementation);

   List<object> paramList = new List<object>(constructorParam.Length);

   foreach(ParameterInfo param in constructorParam)
      paramList.Add(Resolve(param.ParameterType));

   return constructor.Invoke(paramList.ToArray());
}

ジェネリック型Tのオブジェクトを返したいのですが、それができません。

私もそれを型キャストすることができません。2つの依存関係を持つ1つのインターフェースのみを使用しています。(IPredictingFuture、、)EartAndSkyPrediction_BadConnections

インターフェイスタイプに型キャストしようとしています。(私のクライアントコードのメソッドにアクセスするためです。)しかし、それもうまくいきません。

私は何が欠けていますか?

4

3 に答える 3

1

メソッドでcontractは、は実行時にのみ認識されるため、コンパイル時に使用することはできません。呼び出し元によっては、ジェネリック型パラメーターに変更できる場合があります。その場合は、次のことができます。

public static object Resolve(Type contract)
{
   Type Implementation = typeSettings[contract];

   ConstructorInfo constructor = Implementation.GetConstructors()[0];

   ParameterInfo[] constructorParam = constructor.GetParameters();

   if (constructorParam.Length == 0)
      Activator.CreateInstance(Implementation);

   List<object> paramList = new List<object>(constructorParam.Length);

   foreach(ParameterInfo param in constructorParam)
      paramList.Add(Resolve(param.ParameterType));

   return constructor.Invoke(paramList.ToArray());
}

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

おっしゃるように、Resolve(Type)自分自身を再帰的に呼び出し、汎用バージョンではそのように自分自身を呼び出すことができないため、オーバーロードされています。

于 2012-12-07T14:26:54.533 に答える
0

返信ありがとうございます。このオーバーライドされたResolveメソッドを追加しました

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

今、私はタイプを正しく取得します。これはクライアントコードです:

IPredictingFuture predictions;
predictions = IoC.Resolve<IPredictingFuture>();

このように、予測後のインテリセンスは問題なく機能します。

読者のいずれかがIoCコンテナを調理しようとしているためにこの質問にたどり着いた場合、私はこれらのすばらしいリンクを紹介します。

  1. ケンによる33ライナーIoC
  2. Ayendeによる15ライナーIoC
  3. 独自のIoCをコーディングしてはいけない理由に関するAyendeによるフォローアップ投稿
  4. IoCコンテナに関する良いリンク
  5. IoCについて話す別のSOの質問
于 2012-12-10T08:34:32.333 に答える
0

この会場の名前空間を調整して、私はこれを何年も使用しています...

using System;
using System.Collections.Generic;
using DataAccess.Core.DataInterfaces;
using DataAccess.Core.Utils;

namespace StackOverflowExample
{
    public class SimpleIoC<T>
    {
        public T getInstance()
        {
            return getInstance(null);
        }

        public T getInstance(object[] initializationParameters)
        {
            Type type = Activator.CreateInstance(typeof(T), initializationParameters).GetType();
            // Any special initialization for an object should be placed in a case statement
            // using that object's type name
            switch (type.ToString())
            {
                // Example
                //case "DataAccess.Data.ApplicantDao":
                //    // - Do pre-instanciation initialization stuff here -
                //    return (T)Activator.CreateInstance(typeof(T), initializationParameters);
                default:
                    return (T)Activator.CreateInstance(typeof(T), initializationParameters);
            }
        }
    }
}

これが役立つかどうかはわかりませんが、私はこれをビジネスルール評価エンジンの一部として使用しています...

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;

namespace StackOverflowExample
{
    public static class DynamicObjectFactory
    {
        private static readonly object _lock = new object();

        public static object getInstance(string assemblyName, string className)
        {
            Monitor.Enter(_lock);
            try
            {
                System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName);
                return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, null, null, null);
            }
            finally
            {
                Monitor.Exit(_lock);
            }
        }

    public static object getInstance(string assemblyName, string className, object[] constructorParameters)
    {
        Monitor.Enter(_lock);
        try
        {
            System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName);
            return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, constructorParameters, null, null);
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }
}

}

于 2012-12-07T14:47:12.367 に答える