C# 如何在C中使用依赖项注入和继承# 介绍
大家好,我目前正在C#开发一个持久性库。在该库中,我实现了存储库模式,在这里我面临一个实际问题。 以下是我当前实施的一个简化示例,重点是: 持久性库中包含的抽象存储库:C# 如何在C中使用依赖项注入和继承# 介绍,c#,inheritance,dependency-injection,solid-principles,C#,Inheritance,Dependency Injection,Solid Principles,大家好,我目前正在C#开发一个持久性库。在该库中,我实现了存储库模式,在这里我面临一个实际问题。 以下是我当前实施的一个简化示例,重点是: 持久性库中包含的抽象存储库: // Abstract type public interface IRepository<T> { Add(T obj); } // Concete type public class UserRepository : IRepository<User> { public UserRe
// Abstract type
public interface IRepository<T>
{
Add(T obj);
}
// Concete type
public class UserRepository : IRepository<User>
{
public UserRepository(/* Specific dependencies */) {}
Add(User obj) { /* [...] */ }
}
// Decorator
public class LoggingRepository<T> : IRepository<T>
{
private readonly IRepository<T> _inner;
public LoggingRepository<T>(IRepository<T> inner) => _inner = inner;
Add(T obj)
{
Console.Log($"Adding {obj}...");
_inner.Add(obj);
Console.Log($"{obj} addded.");
}
}
// Done using the DI.
IRepositoty<User> repository =
// Add as many decorators as you want.
new LoggingRepository<User>(
new UserRepository(/* [...] */));
// And here is your add method wrapped with some logging :)
repository.Add(new User());
公共抽象类存储库
{
受保护的存储库(
服务伊瑟维西娅,
IServiceB服务(B)
{
/* ... */
}
}
由库用户创建的具体存储库:
// Abstract type
public interface IRepository<T>
{
Add(T obj);
}
// Concete type
public class UserRepository : IRepository<User>
{
public UserRepository(/* Specific dependencies */) {}
Add(User obj) { /* [...] */ }
}
// Decorator
public class LoggingRepository<T> : IRepository<T>
{
private readonly IRepository<T> _inner;
public LoggingRepository<T>(IRepository<T> inner) => _inner = inner;
Add(T obj)
{
Console.Log($"Adding {obj}...");
_inner.Add(obj);
Console.Log($"{obj} addded.");
}
}
// Done using the DI.
IRepositoty<User> repository =
// Add as many decorators as you want.
new LoggingRepository<User>(
new UserRepository(/* [...] */));
// And here is your add method wrapped with some logging :)
repository.Add(new User());
公共类FooRepository:存储库
{
受保护的FoodRepository(
服务伊瑟维西娅,
IServiceB服务b):
基地(服务A、服务B)
{
/* ... */
}
}
问题
好的,在当前代码中,派生类必须知道基类的每个依赖项,这些依赖项可以是确定的,但是如果我向基类添加一个依赖项呢?每个派生类都将中断,因为它们需要将新的依赖项传递给基类。。。因此,目前,我被限制从不更改基类构造函数,这是一个问题,因为我希望我的基类具有进化的可能性这个实现显然打破了开放/封闭原则,但我不知道如何在不打破坚实基础的情况下解决这个问题 要求
- 该库应便于用户使用
- 混凝土存储库应该能够通过DI构建
- 应将一个或多个依赖项添加到抽象存储库中,而不影响派生存储库
- 应该可以使用命名约定在DI容器中注册每个存储库,就像ASP.NET MVC框架与控制器一样
- 如果用户愿意,应该能够在其派生存储库中添加更多依赖项
// Abstract type
public interface IRepository<T>
{
Add(T obj);
}
// Concete type
public class UserRepository : IRepository<User>
{
public UserRepository(/* Specific dependencies */) {}
Add(User obj) { /* [...] */ }
}
// Decorator
public class LoggingRepository<T> : IRepository<T>
{
private readonly IRepository<T> _inner;
public LoggingRepository<T>(IRepository<T> inner) => _inner = inner;
Add(T obj)
{
Console.Log($"Adding {obj}...");
_inner.Add(obj);
Console.Log($"{obj} addded.");
}
}
// Done using the DI.
IRepositoty<User> repository =
// Add as many decorators as you want.
new LoggingRepository<User>(
new UserRepository(/* [...] */));
// And here is your add method wrapped with some logging :)
repository.Add(new User());
公共抽象类存储库
{
公共接口IRepositoryDependencies
{
IServiceA{get;}
IServiceB{get;}
}
受保护的存储库(IRepositoryDependencies)
{
/* ... */
}
}
由库用户创建的具体存储库:
// Abstract type
public interface IRepository<T>
{
Add(T obj);
}
// Concete type
public class UserRepository : IRepository<User>
{
public UserRepository(/* Specific dependencies */) {}
Add(User obj) { /* [...] */ }
}
// Decorator
public class LoggingRepository<T> : IRepository<T>
{
private readonly IRepository<T> _inner;
public LoggingRepository<T>(IRepository<T> inner) => _inner = inner;
Add(T obj)
{
Console.Log($"Adding {obj}...");
_inner.Add(obj);
Console.Log($"{obj} addded.");
}
}
// Done using the DI.
IRepositoty<User> repository =
// Add as many decorators as you want.
new LoggingRepository<User>(
new UserRepository(/* [...] */));
// And here is your add method wrapped with some logging :)
repository.Add(new User());
公共类FooRepository:存储库
{
受保护的存储库(IRepositoryDependencies):
基础(依赖项)
{
/* ... */
}
}
专业人士
- 如果将依赖项添加到基类,则派生类不会中断
- 如果添加依赖项,则必须修改
接口的实现IRepositoryDependencies
- 没有解释如何使用Castle DynamicProxy 2(对我来说这是一种未知的技术)动态生成服务聚合器
- 如果将依赖项添加到基类,则派生类不会中断
- 存储库构造由另一个类管理
- 用户必须为要创建的每个存储库创建一个生成器
- 使用命名约定通过DI注册每个存储库变得越来越困难
- 如果将依赖项添加到基类,则派生类不会中断
- 我认为财产设定者必须公开
仅从DI配置或动态插件获取(但如果您没有动态插件,请不要考虑任何依赖关系,“因为它可能是动态插件”)然后通过构造函数执行所有DI标准经典方法。正如您所要求的,这里是一个通过组合而不是继承来解决此问题的非常基本和粗糙的示例
public class RepositoryService : IRepositoryService
{
public RepositoryService (IServiceA serviceA, IServiceB serviceB)
{
/* ... */
}
public void SomeMethod()
{
}
}
public abstract class Repository
{
protected IRepositoryService repositoryService;
public (IRepositoryService repositoryService)
{
this.repositoryService= repositoryService;
}
public virtual void SomeMethod()
{
this.repositoryService.SomeMethod()
.
.
}
}
public class ChildRepository1 : Repository
{
public (IRepositoryService repositoryService) : base (repositoryService)
{
}
public override void SomeMethod()
{
.
.
}
}
public class ChildRepository2 : Repository
{
public (IRepositoryService repositoryService, ISomeOtherService someotherService) : base (repositoryService)
{
.
.
}
public override void SomeMethod()
{
.
.
}
}
现在,这里的抽象基类和每个子存储库类将只依赖于IRepositoryService
或