私はジェネリックサービスとリポジトリレイヤがあるプロジェクトで作業しています。 Automapperを使ってDTOをエンティティモデルにマップしています。 1つのエンティティは1つ以上のDTOを持つことができます。私の問題は、どのようにDTOがサービス層に戻さなければならないジェネリックリポジトリクラスに伝えるのですか?単一のエンティティ(Automapper)に複数のDTOを持つ汎用リポジトリ
エンティティ
[Table("Entity")]
public class Entity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Required]
public string name { get; set; }
[Required]
public string surname { get; set; }
}
のDTO
public class Contract
{
}
[DataContract]
public class EntityContract: Contract
{
[Required]
[DataMember]
public string name { get; set; }
[Required]
[DataMember]
public string surname { get; set; }
}
[DataContract]
public class EntityPassportContract: Contract
{
[Required]
[DataMember]
public string name { get; set; }
[Required]
[DataMember]
public string surname { get; set; }
[Required]
[DataMember]
public string passport { get; set; }
}
ジェネリックリポジトリ
public interface IGenericRepository<E, DTO>
where E : class
where DTO: class
{
List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null);
}
のGe nericリポジトリの実装
public abstract class GenericRepository<C, E, DTO> : IGenericRepository<T, DTO>
where E : class
where DTO: class
where C : IdentityDbContext<User>, new()
{
//...
public virtual List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null)
{
//...transform DTO queries to E queries and Get IQueriable<E> entity from database
DTO dtoEntity=entity.ProjectTo<DTO>();
return dtoEntity;
}
}
ジェネリックサービス
public interface IService<E, DTO> : IService
where T: class
where DTO: class
{
List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null);
}
一般的なサービスの実装
public abstract class Service<E, DTO> : IService<T, DTO>
where E: class
where DTO: class
{
protected IGenericRepository<E, DTO> repository;
public Service(IGenericRepository<E, DTO> repository,)
{
this.repository = repository;
}
public virtual List<DTO> findBy(Expression<Func<DTO, bool>> query = null, Func<IQueryable<DTO>, IOrderedQueryable<DTO>> orderBy = null,
Expression<Func<DTO, bool>> whereIn = null, int? page = null, int? sizePage = null)
{
return repository.findBy(query, orderBy, whereIn, page, sizePage).ToList();
}
}
エンティティリポジトリおよびサービス
public interface IEntityRepository : IGenericRepository<Entity, Contract>
{
}
public class EntityRepository : GenericRepository<EntitiesDB, Entity, Contract>, IEntityRepository
{
public EntityRepository(IMapper mapper):base(mapper){ }
}
//Service
public interface IEntityService : IService<Entity, Contract>
{
}
public class EntityService : Service<Entity, Contract>, IEntityService
{
private IEntityRepository repo;
public EntityService(IEntityRepository repo) : base(repo)
{
this.repo = repo;
}
}
コントローラ は、私は一般的なサービスでメソッドfindByを呼び出し、DTOを返すために起こっているかを選択します。契約クラスは私のテストの一部でしたが、動作しません。 サービスの各メソッドをDTOのタイプに渡すことがあるかもしれませんか?
[RoutePrefix("api/entity")]
public class EntityController : ApiController
{
public EntityController(IEntityService entityService)
: base(entityService)
{
}
[Route("getEntityByFilter", Name = "getEntityByFilter")]
[HttpGet]
public async Task<IHttpActionResult> getEntityContract(string filter)
{
EntityContract entityContract=entityService.findBy(**Parameters**); //Need to call lambda expressions here so i think i need somehow the type.
return Ok(entityContract);
}
[Route("getEntityByFilter2", Name = "getEntityByFilter2")]
[HttpGet]
public async Task<IHttpActionResult> getEntityPassportContract(string filter)
{
EntityPassportContract entityPassportContract=entityService.findBy(**Parameters**); //Need to call lambda expressions here so i think i need somehow the type.
return Ok(entityPassportContract);
}
}
ありがとうございます!この質問が他の人にも役立つことを願っています!
素晴らしい週末を過ごしましょう!
ルチアーノ
これで、「すべて」を一般的な方法で作成しようとする結果に直面しました。プログラミングはすべてコンテキストに関するもので、まずすべてを分けてから、ある種のジェネリックパターンが見えるときにはジェネリックなアプローチを適用します。 – Fabio
お返事ありがとう@Fabio。私はすでにいくつかの特定のものをやっている特定のリポジトリとサービスを持っています。私はいくつかの簡単なCRUD操作を行うために汎用のものを使用したいと思います。リポジトリごとにfindByを作成すると、エンティティごとに異なる戻り値の型(異なるコントラクト)のコードと同じコードが使用されます。私はそのような状況を避けたい。ありがとう! –
私は、リフレクションなしでこれを行う方法はないと思います。あなたが 'getEntityContract'メソッドでやりたいのであれば、このメソッドはパラメータとして返すタイプについて知っている必要があります。 )、リフレクションを使用して一般的な実行を使用してfindByを実行します。 また、RESTごとにURL名を変更してください。 "api/entity/getEntityByFilter"ではなく "api/entities/byfilter"のように見えます。 別の方法が見つかった場合は、ご意見ください。 – Prince