Help with Common Service Layer (Using EF 4.1) for certain types of entities?
I need some advice on my Service layer. Let's say I have this model:
public abstract class Entity
{
public Guid Id {get;set;}
}
public abstract class Document: Entity
{
public virtual ICollection<Attachment> Attachments{get;set;}
}
public class Attachment: Entity
{
Guid ParentEntityId {get;set;}
//some props....
}
public class Note: Docu开发者_开发技巧ment
{
//some props
}
public class Comment: Document
{
//some props
}
Let's say I have repositories for Notes and Comments. Here is an example of the service layers (the TDto represents the DTOs that flatten the entities):
public interface IMainService<TDto>
{
TDto Create(TDto dto);
void Update(TDto dto);
void Delete(Guid, Id);
}
public interface IDocumentService
{
AttachmentDto AddNewAttachment(AttachmentDto dto);
}
public abstract DocumentService<TEntity>: IDocumentService
{
private IRepository<TEntity> _repository;
public DocumentService(IRepository<TEntity> repository)
{
_repository = repository
}
AttachmentDto AddNewAttachment(AttachmentDto dto)
{
var entity = _repository.GetById(dto.ParentId);
//attachment code
_repository.Update(entity)
_repository.UoW.Commit();
.....
}
public class NoteService: DocumentService<Note>, IMainServcie<NoteDto>
{
public NoteService(INoteRepository repository): base(repository)
{
.....
}
}
public class CommentService: DocumentService<Comment>, IMainServcie<CommentDto>
{
public NoteService(INoteRepository repository): base(repository)
{
.....
}
}
While this works fine, I feel like I would be duplicating code in my application layer. So, if I were using Asp.Net MVC I may have a Comment controller and a Note controller. I would have to create methods for creating attachments on each controller.
I am trying to think of a way to separate out the Document service so I could have a Document controller. The only caveat is that I do not want to expose my entities to the app layer. One thought we had was to type the Document Service methods with the TDto and use some sort of factory to pull the repository and entity types in. Meaning, based of the DTO type we would look-up the related entity is perhaps a switch statement and fire up the entity type and repository for it.
Additional Information: My mappings in EF 4.1 are such that there is a table for Note_Attachments and Comment_Attachments.
What I ended up doing was using a Service factory to get the service I wanted. I also added a genric to my IDocumentService. I am using a Unity container. Something like this:
public static class ServiceFactory
{
public static Services.IDocumentService<TDto> GetDocumentService<TDto>() where TDto : IBridgeDto
{
var dtoName = typeof(TDto).Name;
IDocumentService<TDto> retrunService = null;
switch (dtoName)
{
case "NoteDto":
retrunService = (IDocumentService<TDto>) container.Resolve<INoteService>();
break;
}
return retrunService;
}
}
I have some more refactoring to do, but this, at least, abstracts my service layer from the app a bit.
精彩评论