0

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");
Samantha J T Star
  • 30,952
  • 84
  • 245
  • 427

3 Answers3

0

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?

Community
  • 1
  • 1
Ben Foster
  • 34,340
  • 40
  • 176
  • 285
  • Thanks Ben. I will look into this now. – Samantha J T Star Dec 30 '11 at 10:06
  • Still looking into this. The link you gave does tell me I can add a constructor dependency but then there's part of that page saying I don't need to add one. Doesn't seem clear to me yet. – Samantha J T Star Dec 30 '11 at 10:20
  • If you have access to an object constructed by your container (i.e. via constructor injection) then you can access its `.Container` property. In either case I think the cleaner approach is to inject your container. – Ben Foster Dec 30 '11 at 10:35
  • The problem is the word Product or Package or Content is coming into my update function from javascript. So there's no class being passed around rather it's just a string that has a name that's the same as the class. – Samantha J T Star Dec 30 '11 at 13:33
  • So you have some kind of generic form and want to handle it with a single action method? Why not have an action method for each type of class - doing it in a generic fashion adds a lot of (unnecessary complexity). – Ben Foster Jan 17 '12 at 14:53
0

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.

Kornél Regius
  • 2,989
  • 5
  • 30
  • 39
0

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.

Sebastian Weber
  • 6,766
  • 2
  • 30
  • 49