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 的对象。我做不到。

我也无法对其进行类型转换。我只使用一个具有两个依赖项的接口。( IPredictingFuture, EartAndSkyPrediction, BadConnections)

我正在尝试将其类型转换为接口类型。(为了访问我的客户端代码中的方法。)但这也行不通。

我错过了什么?

4

3 回答 3

1

In your method, contract is only known at runtime, so it cannot be used at compile time. Depending on your callers, you may be able to change it to a generic type parameter, in which case you can do:

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

Overloaded because as you mention, Resolve(Type) calls itself recursively, and the generic version cannot call itself like that.

于 2012-12-07T14:26:54.533 回答
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 回答
0

谢谢各位,回复。我添加了这个重写的 Resolve 方法

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

现在,我得到了正确的类型。这是客户端代码:

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

这样,预测后的智能感知就可以正常工作。

如果任何读者因为试图制作 IoC 容器而遇到这个问题,我会向他们指出这些很棒的链接:

  1. Ken 的 33 班轮 IoC
  2. Ayende 的 15 班轮 IoC
  3. Ayende关于为什么不应该编写自己的 IoC 的后续帖子
  4. 关于 IoC 容器的好链接
  5. 另一个关于 IoC 的SO 问题
于 2012-12-10T08:34:32.333 回答