简体   繁体   English

Activator.CreateInstance-无法使用返回类型

[英]Activator.CreateInstance - Not able to use the return type

I am trying to hand-roll my own IoC tool. 我正在尝试手动开发自己的IoC工具。

This is a part of IoC code: 这是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());
}

I want to return an object of the generic type T. I am not able to do that. 我想返回通用类型T的对象。我无法做到这一点。

I am not able to typecast it either. 我也不能打字。 I am using only one interface with two dependencies. 我只使用一个具有两个依赖项的接口。 ( IPredictingFuture , EartAndSkyPrediction , BadConnections ) IPredictingFutureEartAndSkyPredictionBadConnections

I am trying to typecast it to the Interface type. 我正在尝试将其类型转换为接口类型。 (In order to access the methods in my client code.) But that is not working out either. (为了访问我的客户端代码中的方法。)但这也不起作用。

What am I missing? 我想念什么?

In your method, contract is only known at runtime, so it cannot be used at compile time. 在您的方法中, contract仅在运行时才知道,因此无法在编译时使用。 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. 重载是因为如您所述, Resolve(Type)递归地调用自身,而通用版本则不能这样调用自身。

Adjusting the namespace for this venue, I've used this for years... 调整该场所的名称空间,我已经使用了多年……

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

Not sure if this one will help you, but I use this as part of a Business Rule Evaluation Engine... 不知道这是否对您有帮助,但是我将其用作业务规则评估引擎的一部分...

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

} }

Thanks guys, for the response. 谢谢大家的回应。 I added this overridden Resolve method 我添加了此覆盖的Resolve方法

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

Now, I get the type properly. 现在,我正确地得到了类型。 This is the client code: 这是客户端代码:

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

This way, the intellisense after predictions works just fine. 这样,预测后的智能感知就可以正常工作。

If any of the readers landed up at this question because they are trying to cook up an IoC container, I would point them to these great links: 如果有任何读者因为试图煮熟IoC容器而落入这个问题,我将向他们指出以下重要链接:

  1. 33 liner IoC by Ken Ken的33班轮IoC
  2. 15 liner IoC by Ayende 15班轮IoC by Ayende
  3. Followup post by Ayende on why you should not be coding your own IoC Ayende的后续帖子,介绍为什么不应该编写自己的IoC
  4. Good link about IoC containers 关于IoC容器的良好链接
  5. Another SO question which talks about IoC 另一个关于IoC的SO问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM