简体   繁体   English

Activator.CreateInstance和Ninject

[英]Activator.CreateInstance and Ninject

I have a project I'm working on where I don't know what class I will need to instantiate at compile time. 我有一个正在处理的项目,我不知道在编译时需要实例化哪个类。 I'm trying to use Activator.CreateInstance() to generate a new class for me based on the user input. 我正在尝试使用Activator.CreateInstance()根据用户输入为我生成一个新类。 The code below works well, but I had to change my constructor on my INECCQuery classes to only have a default constructor and not use any sort of dependency injection. 下面的代码运行良好,但是我不得不将我的INECCQuery类上的构造函数更改为仅具有默认构造函数,而不使用任何类型的依赖项注入。 Is there a way I can still use my injection bindings and the Activator.CreatInstance()? 有没有办法我仍然可以使用注入绑定和Activator.CreatInstance()? I'm using Ninject for injection. 我正在使用Ninject进行注射。

    [HttpGet]
    public ActionResult Index(string item) {
      Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper()));
      if (t != null) {
        INECCQuery query = (INECCQuery)Activator.CreateInstance(t);
        var results = query.Check();
        return View("Index", results);
      }
      return View("Notfound");
    }

Constructor injection is always preferred where possible, but a suitable backup would be to leverage property injection. 在可能的情况下,始终首选构造函数注入,但是适当的备份将是利用属性注入。

http://ninject.codeplex.com/wikipage?title=Injection%20Patterns http://ninject.codeplex.com/wikipage?title=Injection%20Patterns

class SomeController {

  [Inject]
  public Object InjectedProperty { get; set; }

}

Based on the assumption that you are trying to replace the Activator.CreateInstance you can inject a Func<T, INECCQuery> or whatever factory you wish to use. 基于您要替换Activator.CreateInstance的假设,您可以注入Func<T, INECCQuery>或希望使用的任何工厂。

You can get Ninject to give you an object of type t at runtime and still get the dependency injection via the constructor.... I do something similar for one case within my application. 您可以获得Ninject在运行时为您提供类型为t的对象,并且仍然可以通过构造函数获取依赖项注入。...在我的应用程序中,我针对一种情况做了类似的事情。

In the Global.asax.cs file, I have the following method: 在Global.asax.cs文件中,我具有以下方法:

    /// <summary>
    /// Gets the instance of Type T from the Ninject Kernel
    /// </summary>
    /// <typeparam name="T">The Type which is requested</typeparam>
    /// <returns>An instance of Type T from the Kernel</returns>
    public static T GetInstance<T>()
    {
        return (T)Kernel.Get(typeof(T));
    }

This depends on a static Kernel reference. 这取决于静态内核引用。

Then, in code, I do 然后,在代码中

var myInfrastructureObject = <YourAppNameHere>.GetInstance<MyInfrastructureType>();

So, I know the type at compile time whereas you don't, but it wouldn't be that difficult to change that. 因此,我在编译时就知道类型,而您却不知道,但是改变它并不难。

You may also wish to look into the ServiceLocator Pattern. 您可能还希望研究ServiceLocator模式。

I've actually found out you can just pass in a second option to the Activator.CreateInstance method and as long as it matches your constructors signature it will work. 实际上,我发现您可以将第二个选项传递给Activator.CreateInstance方法,并且只要它与构造函数的签名匹配即可。 The only problem is if your parameters don't match you will get a runtime error. 唯一的问题是,如果您的参数不匹配,则会出现运行时错误。

Type t = Type.GetType(string.Format("Info.Audit.Query.{0}Query, Info.Audit", item.ToUpper()));
INECCQuery query = (INECCQuery)Activator.CreateInstance(t, repository);

Thanks for all the help. 感谢您的所有帮助。

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

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