Unity Application Block, How pass a parameter to Injection Factory?
Asked Answered
V

2

8

Here what I have now

  Container.RegisterType<IUserManager, UserManagerMock>();
  Container.RegisterType<IUser, UserMock>(
                new InjectionFactory(
                    (c) => c.Resolve<IUserManager>().GetUser("John")));

and get it

Container.Resolve<IProfile>();

I want to pass a name as parameter to Factory so that I will be able to resolve user object with name; Something like this:

 Container.Resolve<IProfile>("Jonh");

How can I change the type registration for this case?

Vitus answered 3/12, 2010 at 7:54 Comment(2)
Personally, I wouldn't attempt to retrieve an IUser/IProfile via service location at all. It's OK to just retrieve the IUserManager via service location and then call GetUser("John") in your code.Limicoline
I agree with John. If possible, try to use dependency injection, instead of service location. This allows you to keep your code free from calls to the container, and have a single (or at most a few) place(s) in your application that call the container.Okechuku
O
7

While most DI frameworks have advanced features to do these types of registrations, I personally rather change the design of my application to solve such a problem. This keeps my DI configuration simple and makes the code easier to understand. Especially for the creation of objects that depend on some context (thread, request, whatever) or have a lifetime that must be managed explicitly, I like to define factories. Factories make these things much more explicit.

In your situation, you want to fetch a profile for a certain user. This is typically something you would like to have a factory for. Here's an example of this:

// Definition
public interface IProfileFactory
{
    IProfile CreateProfileForUser(string username);
}

// Usage
var profile = Container.Resolve<IProfileFactory>()
    .CreateProfileForUser("John");

// Registration
Container.RegisterType<IProfileFactory, ProfileFactory>();

// Mock implementation
public class ProfileFactory : IProfileFactory
{
    public IProfile CreateProfileForUser(string username)
    {
        IUser user = Container.Resolve<IUserManager>()
            .GetUser(username);

        return new UserProfile(user);
    }
}

I hope this helps.

Okechuku answered 4/12, 2010 at 15:24 Comment(2)
I think what confuses me about examples like this (were we call upon the container) is that yor are calling the container directly. Isn't all about it being the otherway around, I wont cite the dodgy proverb but you know what I mean...Epididymis
Steven.. very appreciated, simple, nice, effective.. it works like a charm for meSupertax
A
6

Resolve method allow passing parameters of ResolverOverride. Subtype of ResolverOverride is ParameterOverride which can be used to pass parameter to resolved constructor.

You can do it this way (parameter is Name and passed value is John):

Container.Resolve<IProfile>(new ParameterOverride("Name", "John"));
Allisan answered 3/12, 2010 at 17:7 Comment(1)
True, but you won't get those parameters passed into the factory methodElsy

© 2022 - 2024 — McMap. All rights reserved.