使用和不使用 Unity 注入创建 class 的实例
Create an instance of class with and without injection with Unity
我有一个 API 控制器,在构造函数中 EmployeeService
的一个实例被实例化为 Unity
。
我想在 EmployeeService
的构造函数中注入 myTest 的值,
这意味着 Repository<Employee>
的实例将被创建并且 _myString
的内容将 "TestString"
如果可以怎么设置容器?
谢谢,
[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>());
我的解决方案:
.RegisterType<IEmployeeService, EmployeeService>(
new InjectionConstructor(
typeof(IRepository<Employee>),
"MySetting"));
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
控制器不应该关心从配置文件中读取。这样做违反了Single Responsibility Principle。这会导致可维护性问题;您已经遇到的问题,因为您的设计导致您在测试和配置 DI 库时遇到麻烦。
由于这些是配置值,它们在应用程序的生命周期内不会更改(更改配置文件将导致应用程序重新启动)。因此,控制器没有理由(一遍又一遍)读取它们。相反,您可以在启动期间读取它们一次并将它们注入需要该配置值的class。
如果有多个 classes 需要该配置值,则您的更改很高,以至于您缺少抽象。例如,与其将连接字符串注入许多 classes,不如考虑创建一个 ConnectionFactory,它对那些 classes 隐藏连接字符串,并允许根据请求创建 SqlConnection
。
但在你的情况下,我想象做这样的事情:
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)));
在启动时读取配置值有以下优点:
- 它可以防止您的应用程序代码依赖于配置系统本身。这使您的代码更可重用、可测试和可维护。
- 如果配置不正确,它允许应用程序在启动时快速失败。
- 它允许您在测试套件中验证 DI 配置的正确性,而无需在单元测试项目中拥有完全相同的配置文件。
我有一个 API 控制器,在构造函数中 EmployeeService
的一个实例被实例化为 Unity
。
我想在 EmployeeService
的构造函数中注入 myTest 的值,
这意味着 Repository<Employee>
的实例将被创建并且 _myString
的内容将 "TestString"
如果可以怎么设置容器?
谢谢,
[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>());
我的解决方案:
.RegisterType<IEmployeeService, EmployeeService>(
new InjectionConstructor(
typeof(IRepository<Employee>),
"MySetting"));
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
控制器不应该关心从配置文件中读取。这样做违反了Single Responsibility Principle。这会导致可维护性问题;您已经遇到的问题,因为您的设计导致您在测试和配置 DI 库时遇到麻烦。
由于这些是配置值,它们在应用程序的生命周期内不会更改(更改配置文件将导致应用程序重新启动)。因此,控制器没有理由(一遍又一遍)读取它们。相反,您可以在启动期间读取它们一次并将它们注入需要该配置值的class。
如果有多个 classes 需要该配置值,则您的更改很高,以至于您缺少抽象。例如,与其将连接字符串注入许多 classes,不如考虑创建一个 ConnectionFactory,它对那些 classes 隐藏连接字符串,并允许根据请求创建 SqlConnection
。
但在你的情况下,我想象做这样的事情:
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)));
在启动时读取配置值有以下优点:
- 它可以防止您的应用程序代码依赖于配置系统本身。这使您的代码更可重用、可测试和可维护。
- 如果配置不正确,它允许应用程序在启动时快速失败。
- 它允许您在测试套件中验证 DI 配置的正确性,而无需在单元测试项目中拥有完全相同的配置文件。