C# Autofac、循环参考和解析外键的设计

C# Autofac、循环参考和解析外键的设计,c#,dependency-injection,inversion-of-control,autofac,circular-dependency,C#,Dependency Injection,Inversion Of Control,Autofac,Circular Dependency,我有一个项目,其中我遇到了循环引用问题 我有一个“事件”对象,其中可以有一个“问题”对象列表 我有一个“问题”对象,可以从中获取父“事件” 如果我使用的是实体框架,它将由框架管理,但出于某种原因,我要求不从我的客户机使用实体框架。所以,我尝试模拟EF行为,因为我很确定他们最终会恢复理智,让我使用EF。下面是我如何进行的 public class EventRepository : AbstractRepository<Event>, IEventRepository { pr

我有一个项目,其中我遇到了循环引用问题

我有一个“事件”对象,其中可以有一个“问题”对象列表 我有一个“问题”对象,可以从中获取父“事件”

如果我使用的是实体框架,它将由框架管理,但出于某种原因,我要求不从我的客户机使用实体框架。所以,我尝试模拟EF行为,因为我很确定他们最终会恢复理智,让我使用EF。下面是我如何进行的

public class EventRepository : AbstractRepository<Event>, IEventRepository
{
    private readonly IQuestionRepository questionRepository;
    public EventRepository(IContext context, IQuestionRepository questionRepository)
    {
        this.questionRepository = questionRepository;
    }

    public Event GetNew(DataRow row)
    {
        return new GeEvent(this.questionRepository) { // Load the event from the datarow }
    }

    public class GeEvent : Event
    {
        private readonly IQuestionRepository questionRepository;
        public GeEvent(IQuestionRepository questionRepository)
        {
            this.questionRepository = questionRepository;
        }
        public override List<Question> Questions { get { return this.questionRepository.GetByIdEvent(this.IdEvent); }}
    }
}

public class QuestionRepository : AbstractRepository<Question>, IQuestionRepository
{
    private readonly IEventRepository eventRepository;
    public QuestionRepository(IContext context, IEventRepository eventRepository)
    {
        this.eventRepository = eventRepository;
    }

    public Question GetNew(DataRow row)
    {
        return new GeQuestion(this.eventRepository) { // Load the question from the datarow }
    }

    public class GeQuestion : Question
    {
        private readonly IEventRepository eventRepository;
        public GeQuestion(IEventRepository eventRepository)
        {
            this.eventRepository = eventRepository;
        }
        public override Event Event { get { return this.eventRepository.Get(this.IdEvent); }}
    }
}
公共类事件存储库:AbstractRepository,IEventRepository
{
专用只读IQuestionRepository问题存储库;
公共事件存储库(IContext上下文、IQuestionRepository问题存储库)
{
this.questionRepository=questionRepository;
}
公共事件GetNew(数据行)
{
返回新的GeEvent(this.questionRepository){//从数据行加载事件}
}
公共类事件:事件
{
专用只读IQuestionRepository问题存储库;
公共GeEvent(IQuestionRepository问题存储库)
{
this.questionRepository=questionRepository;
}
公共覆盖列表问题{get{返回this.questionRepository.GetByIdeEvent(this.IdeEvent);}
}
}
公共类问题库:AbstractRepository,IQuestionRepository
{
私有只读IEventRepository事件存储库;
公共问题存储库(IContext上下文、IEventRepository事件存储库)
{
this.eventRepository=eventRepository;
}
公共问题GetNew(数据行)
{
返回新的GeQuestion(this.eventRepository){//从数据行加载问题}
}
公开课问题:问题
{
私有只读IEventRepository事件存储库;
公共问题(IEventRepository事件存储库)
{
this.eventRepository=eventRepository;
}
公共重写事件事件{get{返回this.eventRepository.get(this.IdEvent);}
}
}
所以,正如你所看到的,我有一个“鸡还是蛋”的案例。要创建EventRepository,它需要一个QuestionRepository;要创建QuestionRepository,它需要一个EventRepository。除了直接使用DependencyResolver(这会使存储库(和服务)无法正确测试)之外,我如何管理依赖项以便加载外键“la”实体框架

顺便说一句,我简化了外键的“延迟加载”以保持示例的简单性

顺便说一句,我使用Autofac,如果它在任何方面都有帮助的话


谢谢

我可以建议您的设计是错误的吗?在我看来,当涉及到存储库时,您违反了关注点分离原则

问题存储库的工作不是为您提供作为父对象的事件对象,而是提供用户可以查询EventRepository以获取事件对象的eventId。同样,对于另一个存储库。这样,您就不必到处传递依赖项,而是可以组合您的请求,例如:

var question = _questionRepo.GetNew(row);
var evnt = _eventRepo.Get(question.IdEvent);
此外,正如您所看到的,Autofac并不正式支持循环构造函数\构造函数依赖性


另一种解决方案是将其中一个依赖项更改为属性设置器,然后按照文档所示进行操作。

谢谢您的回答。我知道,这个设计不太理想。我通常会使用实体框架,但客户绝对反对,因为,他说,他的程序员已经有很多东西要学了,EF太远了。。。好。。。EF会处理所有这些无意义的事情,但你知道。。。客户是国王。我想我必须选择属性设置器,直到客户意识到并允许我使用EF。再次感谢你的回答。