我在.NET MVC项目中使用存储库模式,在该项目中,我需要使用相同的功能但有两个不同的结构(有条件地)来获取数据。
更具体地说,在某些情况下,我需要获取具有一堆属性的完整版本的模型,但在某些情况下,我需要获取简单的模型版本(主要出于安全原因)。
到目前为止的代码:
public async Task<IEnumerable<AnswerMinimalDto>> GetQuestionsForUser(int userId)
{
IEnumerable<Answer> foundAnswers = await this.repository.getAnswersByUser(userId);
return Mapper.Map<IEnumerable<AnswerMinimalDto>>(foundAnswers);
}
因此,映射应有条件地发生:
....return Mapper.Map<IEnumerable<AnswerMinimalDto>>(foundAnswers);
或
....return Mapper.Map<IEnumerable<AnswerFullDto>>(foundAnswers);
在这里,我们有两个面向对象的原则相互冲突。首先想到的是要采用两种不同的方法来满足“单一责任”原则。另一方面,通过两种不同的方法完成相同的工作是重复的。
我将采用单一方法。到目前为止,我一直在尝试使用Tuples返回两个模型并从控制器处理所需结果的方法(由于我的方法是异步的,因此无法应用)。但是我对这种方法并不满意。
到目前为止,我想知道是否有任何一种优雅/可取的方式来返回有条件选择的不同结构中的数据。
欢迎任何帮助。
答案 0 :(得分:2)
具有两种不同的方法来完成相同的工作是重复
但是他们没有做同样的工作!一个给您更多数据,另一个给您更少数据。我认为这是两件事。
还试图让控制器决定向客户呈现的内容是一种气味-业务逻辑已向控制器阐明。
正如您所说-您可以有2种方法提供不同的数据。但我走得更远,将接口分开:一个接口,两个实现。 IRepository
和FullRepositoryImpl
和FrugalRepositoryImpl
。
然后让您的DI决定当前需要哪个,因为我敢打赌,这不是一次需要提供有限数据集的情况。
答案 1 :(得分:1)
您可以使用泛型简单地解决此问题:
public async Task<IEnumerable<T>> GetQuestionsForUser<T>(int userId)
{
IEnumerable<Answer> foundAnswers = await this.repository.getAnswersByUser(userId);
return Mapper.Map<IEnumerable<T>>(foundAnswers);
}
IEnumerable<AnswerMinimalDto> a = await GetQuestionsForUser<AnswerMinimalDto>(foundAnswers);
IEnumerable<AnswerFullDto> b = await GetQuestionsForUser<AnswerFullDto>(foundAnswers);
尽管我非常同意trailmax says on this TBH。
IMO DTO对象和Automapper是代码气味/反模式。为什么不只返回基础对象?