簡體   English   中英

循環組件依賴檢測到具有 autofac 依賴注入的存儲庫模式

[英]Circular component dependency detected Repository pattern with autofac dependency injections

我正在使用 db Context 和 Autofac DI 實現通用存儲庫模式,並且我正在使用基於依賴注入的構造函數。

我創建了三層存儲庫模式,它們是:

  • 基礎設施層
  • 模型層
  • 服務層

現在,當我嘗試在 ContactController 中傳遞 IContactService 接口並運行應用程序時,我在 MVC Web 應用程序中使用了這種架構。

我收到循環依賴檢測錯誤。 以下是我的項目代碼。

錯誤

存儲庫代碼:

public class Repository<T> : IRepository<T> where T : class
{
    private InvoiceBillingDbContext db;
    private DbSet<T> dbSet;

    public Repository()
    {
        db = new InvoiceBillingDbContext();
        dbSet = db.Set<T>();
    }
    public IEnumerable<T> GetAll()
    {
        return dbSet.ToList();
    }

    public T GetById(object Id)
    {
        return dbSet.Find(Id);
    }

    public void Insert(T obj)
    {
        dbSet.Add(obj);
        Save();
    }
    public void Update(T obj)
    {
        db.Entry(obj).State = EntityState.Modified;
        Save();
    }
    public void Delete(object Id)
    {
        T getObjById = dbSet.Find(Id);
        dbSet.Remove(getObjById);
    }
    public void Save()
    {
        db.SaveChanges();
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (this.db != null)
            {
                this.db.Dispose();
                this.db = null;
            }
        }
    }

    public void AddRange(List<T> obj)
    {
        dbSet.AddRange(obj);
        Save();
    }

    public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
    {
        return dbSet.Where(predicate);
    }
}

接口 IRepository

public interface IRepository<T> where T : class
{
        IEnumerable<T> GetAll();
        T GetById(object Id);
        IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
        void Insert(T obj);
        void AddRange(List<T> obj);
        void Update(T obj);
        void Delete(Object Id);
        void Save();
}

我的聯系人存儲庫

public class ContactRepository:Repository<Contact>, IContactRepository
{
        private IContactRepository _contractRepo;
        public ContactRepository(IContactRepository contractRepo)
        {
            this._contractRepo = contractRepo;
        }
}

我的 ContactRepository 界面

public interface IContactRepository:IRepository<Contact>
{
}

我的聯系服務

public interface IContactService
{
        void AddContact(Contact contact);
        IEnumerable<Contact> GetContactsByTypeId(int typeId);
}

public class ContactService : IContactService
{
        private readonly IContactRepository _contactRepository;
        public ContactService(IContactRepository contactRepository)
        {
            this._contactRepository = contactRepository;
        }
        public void AddContact(Contact contact)
        {
            _contactRepository.Insert(contact);
        }

        public IEnumerable<Contact> GetContactsByTypeId(int typeId)
        {
            return _contactRepository.Get(i => i.TypeID == typeId);
        }
}

我的控制器

public class ContactController : Controller
{
        // GET: Contact
        private IContactService _contactService;

        public ContactController(IContactService contactService)
        {
            this._contactService = contactService;
        }
        public ActionResult Index()
        {
            return View(new ContactViewModel());
        }

        public ActionResult AddContact(ContactViewModel contact)
        {
            if (ModelState.IsValid)
            {
                var _contactMapper = Mapper.Map<ContactViewModel, Contact>(contact);
                _contactService.AddContact(_contactMapper);
                ViewBag.Message = "Successfully Saved";
                return View("Index",new ContactViewModel());
            }
            ViewBag.Message = "Error Occur Please try Again!";
            return View("Index", new ContactViewModel());
        }
}

和 Autofac 依賴注入

public static void ConfigureContainer()
{
            var builder = new ContainerBuilder();

            // Register all controllers in the Mvc Application assembly
            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            // Registered Warehouse Reservoir Service
            builder.RegisterType<InvoiceRepository>().As<IInvoiceRepository>();
            // Registration Service Layer Service
            builder.RegisterType<InvoiceService>().As<IInvoiceService>();
            builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
            // Registered Warehouse Reservoir Service
            builder.RegisterType<JournalVoucherRepository>().As<IJournalVoucherRepository>();
            // Registration Service Layer Service
            builder.RegisterType<JournalVoucherService>().As<IJournalVoucherService>();



            // Registered Warehouse Reservoir Service
            builder.RegisterType<ContactRepository>().As<IContactRepository>();
            // Registration Service Layer Service
            builder.RegisterType<ContactService>().As<IContactService>();




            // Registration filter
            builder.RegisterFilterProvider();

            var container = builder.Build();

            // Setting Dependency Injection Parser
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

您只有一個IContactRepository實現。 您還有一個通用的IRepository<T>

您的IContactRepository實現將另一個IContactRepository注入其中。 所以你遞歸地解析同一個類並將它注入到自身中。

public class ContactRepository:Repository<Contact>, IContactRepository
{
        private IContactRepository _contractRepo;

        // In order to resolve IContractRepository, the container has to 
        // resolve another IContractRepository to inject into it. 
        // And another one to inject into that. It's recursive.
        public ContactRepository(IContactRepository contractRepo)
        {
            this._contractRepo = contractRepo;
        }
}

您的示例未顯示ContactRepository如何使用注入其中的IContactRepository 但是這個

public interface IContactRepository:IRepository<Contact>
{
}

表明它使用的方法與IRepository<Contact>方法完全相同,因為IContactRepository除了這些方法之外沒有任何方法。

所以你很可能只需要修改ContactRepository來注入IRepository<Contact> ,而不是IContactRepository

public class ContactRepository:Repository<Contact>, IContactRepository
{
        private IRepository<Contact> _contractRepo;

        public ContactRepository(IRepository<Contact> contractRepo)
        {
            this._contractRepo = contractRepo;
        }
}

這很容易被忽視,因為兩個接口都有完全相同的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM