TheBoubou
TheBoubou

Reputation: 19903

Create an instance of class with and without injection with Unity

I have an API controller, in the constructor an instance of EmployeeService is instantiated with Unity.

I'd like inject the value of myTest in the constructor of EmployeeService, that's means an instance of Repository<Employee> will be created and the content of _myString will "TestString"

If it's possible how set the container ?

Thanks,

[RoutePrefix("api/employee")]
public class EmployeeController : ApiController
{
    string myTest = "TestString";
    readonly IEmployeeService _employeeService;

    public EmployeeController(IEmployeeService employeeService)
    {
        _employeeService = employeeService;
    }
}

public class EmployeeService : ServiceBase, IEmployeeService
{
    private readonly IRepository<Employee> _repoEmployee;
    private readonly string _myString;

    public EmployeeService(IRepository<Employee> repoEmployee, string myString)
    {
        _repoEmployee = repoEmployee;
        _myString = myString
    }
}

container
 .RegisterType<IRepository<Employee>, Repository<Employee>>()
 .RegisterType<IEmployeeService, EmployeeService>());

My Solution :

.RegisterType<IEmployeeService, EmployeeService>(
    new InjectionConstructor(
            typeof(IRepository<Employee>), 
            "MySetting"));

Upvotes: 1

Views: 462

Answers (1)

Steven
Steven

Reputation: 172646

To use in the service class some parameters (keys) coming from the web.config. These parameters are read in the controller and send to the service class

The controller should not be concerned with reading from the configuration file. In doing so, it violates the Single Responsibility Principle. This causes maintainability issues; issues that you are already experiencing, since your design causes you trouble with testing and configuring your DI library.

Since these are configuration values, they will not change during the lifetime of the application (changing the config file will cause the application to restart). Because of this, there is no reason for the controller to read them (over and over again). Instead, you can read them once during startup and inject them into the class that needs that configuration value.

In case there are multiple classes that need that configuration value, you changes are high that you are missing an abstraction. For instance, instead of injecting a connection string into many classes, consider creating an ConnectionFactory that hides the connection string from those classes and allows creating a SqlConnection on request.

But in your case, I imagine doing something like this:

TimeSpan timeOut = TimeSpan.FromSeconds(Int32.Parse(
    ConfigurationManager.AppSettings["timeOut"]));

container.RegisterType<IRepository<Employee>, Repository<Employee>>();
container.RegisterType<IEmployeeService, EmployeeService>());
container.Register<IEmployeeService>(new InjectionFactory(c =>
    new EmployeeService(
        c.Resolve<IRepository<Employee>>(),
        timeOut)));

Reading configuration values at start up has the following advantages:

  • It prevents your application code from depending on the configuration system itself. This makes your code more reusable, testable and maintainable.
  • It allows the application to fail fast at start up in case it is configured incorrectly.
  • It allows you to verify the correctness of your DI configuration in a test suite, without having to have the exact same configuration file in your unit test project.

Upvotes: 1

Related Questions