1
votes

Is there any way to resolve the instance of a class at the controller level? I would like to override the previous instance created by unity and assign this new value via the controller.

Problem is I am not sure how to access the unity container in the web app controller.

Here is my code:

Repository:

public class UserRepository: IUserRepository
{
    private UserInformation _userInfo; 
    public UserRepository(string headerValue)
    {       
        _userInfo = LoadUserData(headerValue);
    }

    public UserInformation GetUserInfo()
    {       
        return _userInfo;
    }
}

public class UserInformation
{
      public string FirstName;
      public string LastName;
}

Unity Configuration:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //Some code omitted
        config.DependencyResolver = new UnityDependencyResolver(UnityConfig.RegisterComponents());            
    }
}

public static class UnityConfig
{
    public static UnityContainer RegisterComponents()
    {
        //Unity Configuration
        var container = new UnityContainer();

        container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor("DummyHeaderValue"));          
        return container;
    }
}

Controller:

public class CustomerController : ApiController
{   
    public CustomerController()
    {
        //Something like this
        container.Resolve<UserRepository>(new InjectionConstructor(Request.GetHeader("RealHeaderValueFromHttpRequest")));
    }   
}

Then I should be able to use the updated UserRepository instance throughout the application.

Any thoughts on how to achieve this?

Edit: As pointed out by @Nkosi I don't have access to Request in controller constructor. So let me rephrase my question again:

How would I initialise UserRepository with UserInformation object which contains details about the current user? The reason I want to do this is that throughout my application I want user details and I don't want to pass User Id from each method

Something like this: From any method throughout application

UserInformation obj = _userRepository().GetUserInfo();
1
You are using a service locator pattern, when you should be using explicit dependency principle and inject the dependency into the constructor. public CustomerController(IUserRepository repository) { ... } - Nkosi
Also note that the request is not available as yet when accessed in the constructor of the controller. You will need to rethink the design of the repository and controller. - Nkosi
My main objective here is to initialize UserRepository constructor with the value from the Http request header using unity. Any thoughts? - Shaggy
I understand what you want to do. What I am telling you is you wont have access to the request in the constructor at the time that the repository is being initialized. - Nkosi

1 Answers

2
votes

Create an abstraction to get access to the request

public interface IHeaderService {
    string RealHeaderValueFromHttpRequest();
}

Its Implementation will have access to the context and request to get the desired functionality

public class HeaderService : IHeaderService {
    public string RealHeaderValueFromHttpRequest() {
        return HttpContext.Current.Request.Headers["RealHeaderValueFromHttpRequest"];
    }
}

The service will now be explicitly injected into the dependent repository

public class UserRepository: IUserRepository {
    private readonly IHeaderService headerService;

    public UserRepository(IHeaderService headerService) { 
        this.headerService = headerService;
    }

    public UserInformation GetUserInfo() {
        var headerValue = headerService.RealHeaderValueFromHttpRequest();
        var _userInfo = LoadUserData(headerValue);
        return _userInfo;
    }

    //...
}

The repository will then also be explicitly injected into dependent controllers.

public class CustomerController : ApiController {
    private readonly IUserRepository repositoty;

    public CustomerController(IUserRepository repositoty) {
        this.repository = repository;        
    }

    public IHttpActionResult SomeAction() {
        //NOTE: Only access user info in a controller action
        var userInfo = repository.GetUserInfo();

        //... use user info.
    }

    //...
}

Now all that is left is to make sure all abstractions and their implementations are registered with the dependency container

public static class UnityConfig {
    public static UnityContainer RegisterComponents() {
        //Unity Configuration
        var container = new UnityContainer();

        container.RegisterType<IUserRepository, UserRepository>();
        container.RegisterType<IHeaderService, HeaderService>();

        return container;
    }
}