简体   繁体   中英

How can I create an instance of a class with resolve from inside my method using Unity?

I have been using Unity to create classes with constructor injection like this:

 public class ProductsController : BaseController
    {
        public ProductsController(
            IService<Account> accountService,
            IService<Product> productService)
        {
            _account = accountService;
            _product = productService;
        }

Bootstrapper:

private static IUnityContainer BuildUnityContainer()
        {
            CloudStorageAccount storageAccount;
            storageAccount = CloudStorageAccount.FromConfigurationSetting("DEV_DataConnectionString");
            var container = new UnityContainer();
            container.RegisterType<   IService<Account>, AccountService   >();
            container.RegisterType<   IService<Product>, ProductService   >();
            container.RegisterType<IAzureTable<Product>, AzureTable<Product>>(new InjectionConstructor(storageAccount, "TestProducts"));
            return container;
        }

Now I need to create an instance of a service instance "on the fly" from within my method. Something like this:

    public void Update(string serviceClassName) {

        var serviceClass = new container.Resolve<IService<Product>>();

But there are some things I don't understand.

  • First of all do I need to create a new container? I assume I need to reference the container I already created but I can't find any reference on how to do that.
  • Second here I have hardcoded Product but what I need is to be able to pass in the word "Product" as a parameter and then have it constructed.

How can I create my class ?

Update

Not tested yet but I believe the solution for naming of my class may require me to register my class as follows:

container.RegisterType<   IService<Product>, ProductService   >("productService");

Why not make use of generics rather than using strings:

public void Update<T>(T item) {
    var serviceClass = container.Resolve<IService<T>>();
    serviceClass.DoSomething();
}

Usage:

Update(someProduct); 
// generic type is inferred. Same as - Update<Product>(someProduct)

I believe you can get a reference to your container by adding a constructor dependency of type IUnityContainer - see Can a unity container pass a reference of itself as a constructor parameter?

Make a global public static class, and add a public static unitycontainer property to it. Then you can use it globally.

For the class creation... you can use reflection like this for resolving :

public static class MyContainer
{
    public static UnityContainer Container { get; set; }
}

class ServiceClass<T>
{}

class ReturnClass
{}

class Program
{
    static void Main(string[] args)
    {

    }

    ReturnClass DoResolve(string name)
    {
        Type type = typeof (UnityContainer);
        MethodInfo genericMethod = type.GetMethod("Resolve").MakeGenericMethod(typeof(ServiceClass<>).MakeGenericType(new Type[]{Type.GetType(name)}));
        object invoke = genericMethod.Invoke(MyContainer.Container,null);
        return (ReturnClass) invoke;
    }
}

And after this you can just call this DoResolve()...

I hope I helped in some way.

Why do you use a magic string to dispatch updates to a service? If you know the string on the client side you could just as well call the appropriate service method UpdateProduct(...) , UpdateCustomer(...) . And then you would not need any guesswork on the service side.

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