C# 使用Autofac动态解析依赖项
像我现在这样动态地解决依赖关系好吗。在任何地方,都建议使用构造函数注入。我真的不明白我这样做的缺点。代码片段如下所示 Employee.csC# 使用Autofac动态解析依赖项,c#,dependency-injection,asp.net-web-api2,autofac,ioc-container,C#,Dependency Injection,Asp.net Web Api2,Autofac,Ioc Container,像我现在这样动态地解决依赖关系好吗。在任何地方,都建议使用构造函数注入。我真的不明白我这样做的缺点。代码片段如下所示 Employee.cs public class Employee { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Department Department { get; set; } } pub
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
IRepository.cs
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
公共接口IRepository,其中TModel:class
{
无效添加();
IEnumerable GetAll();
IEnumerable GetByID();
}
Repository.cs
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
公共类存储库:IRepository,其中TModel:class
{
公共无效添加()
{
抛出新的NotImplementedException();
}
公共IEnumerable GetAll()
{
抛出新的NotImplementedException();
}
公共IEnumerable GetByID()
{
抛出新的NotImplementedException();
}
}
EmployeeController.cs
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
公共类HomeController:ApicController
{
IComponentContext_容器;
公共HomeController(IComponentContext容器)
{
这个._容器=容器;
}
使用()的公共存储库,其中TModel:class
{
var repository=_container.Resolve(typeof(IRepository));
将存储库作为存储库返回;
}
[HttpGet]
公共IEnumerable GetEmployees()
{
使用().GetAll()返回;
}
}
Global.asax
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
var container = builder.Build(Autofac.Builder.ContainerBuildOptions.None);
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
}
受保护的无效应用程序\u Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder=new ContainerBuilder();
RegisterAppController(Assembly.getExecutionGassembly());
builder.RegisterGeneric(typeof(Repository)).As(typeof(IRepository));
var container=builder.Build(Autofac.builder.ContainerBuildOptions.None);
var webApiResolver=新的AutofacWebApiDependencyResolver(容器);
GlobalConfiguration.Configuration.DependencyResolver=webApiResolver;
}
假设我有5个存储库,构造函数注入将解决我提出的请求的所有5个依赖项。我可能不会为每个请求使用5个存储库。因此,我想通过使用()传递类型来动态解析依赖关系,就像我在
中所做的那样。如有任何建议,将不胜感激。。!!谢谢你 不要直接在应用程序组件内部使用容器;这会导致各种各样的问题,比如可维护性和可测试性问题。从应用程序代码中直接解析实例称为服务定位器
作为第一次重构,您可以改为应用该模式。工作单元允许访问底层存储库。例如:
public interface IUnitOfWork
{
IRepository<TModel> Repository<TModel>();
}
public sealed class HomeController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._unitOfWork.Repository<Employee>().GetAll();
}
}
此模式大大简化了应用程序组件,并防止了服务定位器反模式通常导致的缺点
尽管应用工作单元模式可能是朝着正确方向迈出的有用一步,但更好的方法是直接跳过工作单元,直接将所需的存储库注入到应用程序组件中:
public sealed class HomeController : ApiController
{
private readonly IRepository<Employee> _employeeRepository;
public HomeController(IRepository<Employee> employeeRepository)
{
this._employeeRepository = employeeRepository;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._employeeRepository.GetAll();
}
}
公共密封类HomeController:ApicController
{
私人只读IRepository\u employeeRepository;
公共家庭管理员(IRepository employeeRepository)
{
这._employeeRepository=employeeRepository;
}
[HttpGet]
公共IEnumerable GetEmployees()
{
返回此项。_employeeRepository.GetAll();
}
}
假设我有5个存储库,构造函数注入将解决我提出的请求的所有5个依赖项。我可能不会为每个请求使用5个存储库
请注意,从性能角度来看,您通常不应该关心是否使用依赖项。在大多数情况下,Autofac的速度足够快,这不太可能在生产系统中造成任何性能问题
然而,从设计的角度来看,如果一个类有许多依赖项,而方法只使用其中的一些依赖项,那么您应该更加担心。这意味着类中的方法几乎没有内聚性。这表明该类应划分为多个较小的类;它基本上是使用直接使用容器来考虑反模式的服务定位器模式。这里有更多信息:我个人会把它分成多个控制器,只注入所需的存储库。@Praveen说,因此,请不要直接使用容器。在idependencysolver.GetService
中使用IoC容器解析已注册的类型就足够了。嘿,Steven,你知道这一点吗