unity resolve instance at web api controller

2019-08-01 09:34发布

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条回答
叛逆
2楼-- · 2019-08-01 09:58

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;
    }
}
查看更多
登录 后发表回答