我对OOP的基本概念缺乏了解。这是一个示例:
说我有一个基本存储库,它由3个不同的类派生。基类需要在构造函数中通过依赖注入注入dbContext。因此,每次我实例化子类时,子类都必须传递dbContext。要求很简单:基类应为子类实例化Context。那可能吗?我不希望子类担心上下文。我只想让他们打电话。
这是我的基础课。
public class CastingBaseRepository<TEntity> : ICastingBaseRepository<TEntity> where TEntity : class, IEntity
{
private readonly CastingContext _context;
public CastingBaseRepository(CastingContext context) => _context = context ?? throw new ArgumentNullException(nameof(context));
// Context property
public CastingContext Context => _context;
}
以下是子类的情况:
public class CommercialJobsRepository : CastingBaseRepository<Audition>, ICommercialJobsRepository
{
/* I do not want to use base(context) here. I need a way for this class to just call Context property from the derived class.. Possible? */
private CastingContext _context;
public CommercialJobsRepository(CastingContext context) : base(context)
{
_context = context;
}
public async Task<IList<OpenJobs>> GetOpenJobs()
{
// test code
var tt = await _context.Audition.Take(10).ToListAsync();
return new List<OpenJobs>();
}
}
这是我的上下文课程
public partial class CastingContext : DbContext
{
public virtual DbSet<Audition> Audition { get; set; }
public CastingContext(DbContextOptions<CastingContext> options) : base(options)
{
}
}
这是startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// DB Context
services.AddDbContextPool<CastingContext>(options => { options.EnableSensitiveDataLogging(); options.UseSqlServer(Configuration.GetConnectionString("dbCast")); });
}
}
我正在使用策略模式来确定在运行时将访问哪个子类。那也需要CastingContext注入丑陋的构造函数。关键是,应该只有一个类将上下文公开给所有派生类,或者通过静态方法公开。您能帮我了解如何做吗?
这是我的策略课程:
public class JobsStrategyContext
{
private readonly CastingContext _context;
private readonly Dictionary<eBreakdownTypes, IJobsRepository> Strategies =
new Dictionary<eBreakdownTypes, IJobsRepository>();
public JobsStrategyContext(CastingContext context)
{
_context = context;
Strategies.Add(eBreakdownTypes.Ftv, new FtvJobsRepository(_context));
Strategies.Add(eBreakdownTypes.Commercial, new CommercialJobsRepository(_context));
Strategies.Add(eBreakdownTypes.Theatre, new TheatreJobsRepository(_context));
}
public async Task<IList<OpenJobs>> GetOpenJobsBySubType(eBreakdownTypes breakdownType)
{
return await Strategies[breakdownType].GetOpenJobs();
}
}
答案 0 :(得分:2)
不,您不能同时使用依赖注入和在基类中硬编码依赖的实例化。如果要从外部使用者注入依赖性,则它需要通过派生的构造函数传递。
充其量,您可以传递一个服务定位器,基础构造函数然后使用该服务定位器来获取dbcontext,但是您仍在处理派生类中的服务定位器。但是service locators are no longer considered good practice因为它们具有显着的缺点,例如降低了可读性/可用性,并且在足够大的代码库中变得难以处理。
尽管从技术上讲它可以实现您想要的目标,但是不要开始使用静态服务定位器。成本远大于收益。
但是,问题的开始对我而言并不合理。如果您使用的是依赖注入,那么我假设您正在使用某种自动注入,而不必手动实例化所有依赖。
是的,您仍然需要提及dbcontext作为(派生的和基本的)构造函数参数,但是派生类不需要处理它(除了将其传递给基本的构造函数。这样做的工作量很小,并且允许在依赖注入方面获得最大的自由度。
继承是设计使然的方式。
答案 1 :(得分:1)
这是C#语言的功能限制。您没有必须在子类中提供与基类相同的构造函数,但是您必须满足基类中的那些构造函数。例如:
public class BaseClass
{
public BaseClass(Dependency dep) {}
}
public class ChildClass
{
public ChildClass(Dependency dep) : base(dep) {}
}
或者:
public class ChildClass
{
public ChildClass() : base(new Dependency()) {}
}
无论哪种情况,您都必须以某种方式向基类构造函数提供Dependency
实例,但是您可能选择不实际构造具有该依赖关系的子类,而是在内部获取它。
但是,实际上,DbContext
之类的东西依赖于要注入的依赖项,它将需要一直携带该依赖项:您的子类将需要一个构造函数,可以按顺序对其进行注入然后传递给基类构造函数。
答案 2 :(得分:1)
您必须通过子类提供依赖项,因为在创建子类的实例时,基类也将被构造,因此必须提供依赖项。
当然,为了简化编码和管理这些依赖关系,您可以使用使用 Unity 之类的IoC容器来处理自动依赖关系注入(支持构造函数,属性的Unity Application依赖关系注入容器,以及方法调用注入)