简体   繁体   中英

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. 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. Is there a way I can still use my injection bindings and the Activator.CreatInstance()? I'm using Ninject for injection.

    [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

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.

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.

In the Global.asax.cs file, I have the following method:

    /// <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.

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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