0

이 상황이 있습니다 :순환 참조 + IoC

웹 프로젝트 - Unity 3 IoC를 사용하여 비즈니스 클래스를 호출하는 중입니다. 웹 프로젝트에는 비즈니스 프로젝트가 표시되지 않습니다. 단지 Contracts Project를 참조합니다.

namespace Biblioteca.Web.Controllers 
{ 
    public class HomeController : Controller 
    { 
     public ActionResult Index() 
     { 
      return View(); 

      var Autor = Inject.Resolve<IAutorBO>(); 
     } 
    } 
} 

비즈니스 프로젝트 - 나는 여기 (아래 참조) 데이터 프로젝트에 클래스를 AutorDO 가리 키도록 유니티 3의 IoC를 사용합니다. 비즈니스 프로젝트에는 데이터 프로젝트가 표시되지 않습니다.

namespace Biblioteca.Data 
{ 
    public sealed partial class AutorBO : IAutorBO 
    {     
     #region Atributos 

     private IAutorDO AutorDO = Inject.Resolve<IAutorDO>(); 

     #endregion 

     #region Métodos Interface 

     public IQueryable<DTOAutor> GetAll() 
     { 
      return AutorDO.GetAll(); 
     } 

     public DTOAutor GetById(int id) 
     { 
      return AutorDO.GetById(id); 
     } 

     void IAutorBO.Insert(DTOAutor dto) 
     { 
      AutorDO.Insert(dto); 
     } 

     void IAutorBO.Delete(DTOAutor dto) 
     { 
      AutorDO.Delete(dto); 
     } 

     void IAutorBO.Update(DTOAutor dto) 
     { 
      AutorDO.Update(dto); 
     } 

     //IQueryable<DTOAutor> IAutorBO.SearchFor(Expression<Func<Autor, bool>> predicate) 
     //{ 
     // return AutorDO.SearchFor(predicate); 
     //} 

     IQueryable<DTOAutor> IAutorBO.GetAll() 
     { 
      return AutorDO.GetAll(); 
     } 

     DTOAutor IAutorBO.GetById(int id) 
     { 
      return AutorDO.GetById(id); 
     } 

     #endregion 

     #region Outros Métodos 

     #endregion 
    } 
} 

데이터 액세스 프로젝트 - 여기 데이터 프로젝트입니다.

namespace Biblioteca.Data 
{ 
    public sealed partial class AutorDO : IAutorDO 
    { 
     #region Atributos 

     Repository<Autor> repository = new Repository<Autor>(); 

     #endregion 

     #region Implementações Interface 

     /// <summary> 
     /// Implementação do método de interface Insert 
     /// </summary> 
     /// <param name="dto"></param> 
     void IAutorDO.Insert(Transport.DTOAutor dto) 
     { 
      Autor entity = AssemblerAutor.ToEntity(dto); 
      repository.Insert(entity); 
     } 

     /// <summary> 
     /// Implementação do método de interface Delete 
     /// </summary> 
     /// <param name="dto"></param> 
     void IAutorDO.Delete(Transport.DTOAutor dto) 
     { 
      Autor entity = AssemblerAutor.ToEntity(dto); 
      repository.Delete(entity); 
     } 

     /// <summary> 
     /// Implementação do método de interface Update 
     /// </summary> 
     /// <param name="dto"></param> 
     void IAutorDO.Update(Transport.DTOAutor dto) 
     { 
      Autor entity = AssemblerAutor.ToEntity(dto); 
      repository.Update(entity); 
     } 

     /// <summary> 
     /// Implementação do método de interface SearchFor 
     /// </summary> 
     /// <param name="dto"></param> 
     /// <returns></returns> 
     //IQueryable<Transport.DTOAutor> IAutorDO.SearchFor(Expression<Func<Autor, bool>> predicate) 
     //{ 
     // IQueryable<Autor> list = repository.SearchFor(predicate); 
     // IQueryable<Transport.DTOAutor> dtoList = (IQueryable<Transport.DTOAutor>)AssemblerAutor.ToDTOs(list); 
     // return dtoList; 
     //} 

     /// <summary> 
     /// Implementação do método de interface GetAll 
     /// </summary> 
     /// <returns></returns> 
     IQueryable<Transport.DTOAutor> IAutorDO.GetAll() 
     { 
      IQueryable<Autor> list = repository.GetAll(); 
      IQueryable<Transport.DTOAutor> dtoList = (IQueryable<Transport.DTOAutor>)AssemblerAutor.ToDTOs(list); 
      return dtoList; 
     } 

     /// <summary> 
     /// Implementação do método de interface GetById 
     /// </summary> 
     /// <param name="id"></param> 
     /// <returns></returns> 
     Transport.DTOAutor IAutorDO.GetById(int id) 
     { 
      Autor entity = new Autor(); 
      Transport.DTOAutor dto = new Transport.DTOAutor(); 

      using (var ctx = new BibliotecaContext()) 
      { 
       entity = repository.GetById(id); 
       dto = AssemblerAutor.ToDTO(entity); 
      } 

      return dto; 
     } 

     #endregion 
    } 
} 

비즈니스 및 데이터 프로젝트 모두 IoC 구현에 사용되는 모든 Unity 3 IoC 인터페이스가있는 계약 프로젝트를 참조합니다. 아래의 IoC를 구현하는 데 사용되는 인터페이스는 다음과 같습니다

namespace Biblioteca.Contracts 
{ 
    public interface IAutorBO 
    { 
     #region Métodos CRUD 

     void Insert(DTOAutor dto); 
     void Delete(DTOAutor dto); 
     void Update(DTOAutor dto); 
     //IQueryable<DTOAutor> SearchFor(Expression<Func<Autor, bool>> predicate); 
     IQueryable<DTOAutor> GetAll(); 
     DTOAutor GetById(int id); 

     #endregion 
    } 
} 

namespace Biblioteca.Contracts 
{ 
    public interface IAutorDO 
    { 
     #region Métodos CRUD 

     void Insert(DTOAutor dto); 
     void Delete(DTOAutor dto); 
     void Update(DTOAutor dto); 
     //IQueryable<DTOAutor> SearchFor(Expression<Func<Autor, bool>> predicate); 
     IQueryable<DTOAutor> GetAll(); 
     DTOAutor GetById(int id); 

     #endregion 
    } 
} 

을 보완하기 위해, 나는 일반적인 저장소를 사용, 아래 : 나는 모든 클래스에서 주석 처리 방법이

namespace Biblioteca.Data 
{ 
    /// <summary> 
    /// Interface para classe genérica para métodos CRUD 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    public interface IRepository<T> 
    { 
     void Insert(T entity); 
     void Delete(T entity); 
     void Update(T entity); 
     IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate); 
     IQueryable<T> GetAll(); 
     T GetById(int id); 
    } 
} 

namespace Biblioteca.Data 
{ 
    /// <summary> 
    /// Classe genérica para métodos CRUD da camada Data 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    public class Repository<T> : IRepository<T> where T : class 
    { 
     #region Attributes 

     protected DbSet<T> dbset; 
     protected DbContext ctx; 

     #endregion 

     #region Constructor 

     public Repository() 
     { } 

     public Repository(DbContext ctx) 
     { 
      this.ctx = ctx; 
      dbset = ctx.Set<T>(); 
     } 

     #endregion 

     #region IRepository<T> Members 

     public void Insert(T entity) 
     { 
      if (dbset.Contains(entity)) 
      { 
       Update(entity); 
      } 
      else 
      { 
       dbset.Add(entity); 
      } 
     } 

     public void Delete(T entity) 
     { 
      dbset.Remove(entity); 
     } 

     public void Update(T entity) 
     { 
      using (ctx) 
      { 
       ctx.Set<T>().Attach(entity); 
       ctx.SaveChanges(); 
      } 
     } 

     public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate) 
     { 
      return dbset.Where(predicate); 
     } 

     public IQueryable<T> GetAll() 
     { 
      return dbset; 
     } 

     public T GetById(int id) 
     { 
      return dbset.Find(id); 
     } 

     #endregion 
    } 
} 

알 수 있습니다. 순환 적 종속성을 야기하므로이 방법을 구현할 수 없습니다.

데이터 프로젝트를 참조하는 계약 프로젝트가 있습니다. 하지만 데이터 프로젝트에있는 엔터티 Autor가 필요하기 때문에 "SearchFor"메서드를 사용할 수 없습니다.

비즈니스 및 데이터 모두 엔티티 클래스가 필요하므로 동일한 메소드 서명이 있어야합니다.

웹이 비즈니스 및 비즈니스를 참조하지 않고 Data를 참조하지 않고 IoC를 사용하도록 허용하고 Entity를 매개 변수로 전달할 수있는 다른 방법을 만들 수있는 방법이 필요합니다.

어떤 제안? 나는 이미 세 번째 프로젝트를 만들려고 노력했지만 그것을 작동시킬 수는 없다. Reflection을 사용할 수 있습니까? 가능하다면 어떻게?

나는 어떤 제안을 주셔서 감사합니다.

+0

누구나 그 문제를 어떻게 해결할 수 있는지 알고 있습니까? 그것은 정말로 중요합니다. 왜냐하면 제가 건축을 마무리해야하기 때문입니다. 감사. – Olivertech

답변

0

순환 의존성이있는 경우 아키텍처를 수정해야한다는 단서가됩니다.

"데이터 프로젝트를 참조하는 계약 프로젝트"가 필요한 경우 계약에서 데이터를 참조하여 엔터티를 가져올 수 없습니다. "비즈니스 및 데이터에 엔티티 클래스가 필요합니다"라고 말하면 엔티티 Autor를 엔티티 프로젝트에 보관하지 않는 것이 좋습니다.

데이터 -> 참조 계약 - 대신 데이터의 계약 프로젝트에서 엔티티를 정의> 엔티티

또는 대안으로

를 참조 ->는 엔티티에게 이 계약을 참조합니다.