我只需要几个链接到文章中,我可以和一些基本的解释宣读了关于MVC(C#)中使用的不同的模式。
目前我倾向于使用视图模型模式建立我的web应用程序。 对于每一个观点我有一个视图模型。 我喜欢这种方法,纯粹是因为那里可以是未从模型需要那么多的垃圾,我可以在这里使用了一些基本的数据注解。
我现在还构建我的ViewModels视图模型本身(不能确定这是否是正确的吗?),这样我可以保持我的控制器尽可能简单。
然而有我发现自己加入我的控制器内的很多逻辑的时候,我会以为这是罚款也为我,是控制器是有什么。
现在,基于上述,我说我可以很愉快地建立我的应用程序没有任何重大问题。 但是同时做我的代码示例等正常浏览我经常发现有在那里使用不同的开发商做我上面做的基本上就是这么多其他的方式,我想解释的,他们都结合在一起。
我经常看到提到的“用你的资料库做等等等等” ..我使用repositorys“有时”,但是这主要是针对模型的查询,我知道我会重新使用在未来,它总是变成了一个位的垃圾场。 什么是最好的做法吗?
我也看到提到的“接口”和“服务层”我完全失去了这里。多数的例子我似乎只是添加越来越多的步骤来达到同样的目的。 如何/为什么使用它们?
我不能说这是最好的做法,但是这是我用什么,为什么,在这里,我们去:
1.库。
它们的构造是这样的:
有三种基本接口, IRead<>
IReadCreate<>
和IReadCreateDelete<>
interface IRead<T>
{
T FindOne(int id);
IQueryable<T> GetOne(int id);
IQueryable<T> FindAll(Expression<Func<T, bool>> predicate);
}
interface IReadCreate<T> : IRead<T>
{
T Create();
void Create(T entity);
}
interface IReadCreateDelete<T> : IReadCreate<T>
{
void Delete(int id);
void Delete(T entity);
void DeleteWhere(Expression<Func<T, bool>> predicate);
}
其他所有接口看起来就像这样:
interface ICategoriesRepository : IReadCreate<Category>
{
IQueryable<Category> GetAllActive();
}
和所有的人都提供它们所依赖的数据源上附加有用的功能。 这意味着,我不能在我的实现仓库到达其他类型化资料库。 这应该在服务完成。 (往下看。)
这种方法的主要目的是展示调用代码(从另一个组件,因为我所有的仓库,服务及其他合同在单独的DLL项目中定义(如接口)),它可以做什么(如阅读和创建项目)什么它不能做(如删除的项目)。
2.服务
服务和最佳的方式来实现你的业务逻辑。 他们应该实现您所有的重要逻辑方法。 为了更好地实现那样的实施,他们将需要一些仓库depency,这里谈到的Dependency Injector
。 我更喜欢使用Ninject,因为它让我注入这样的依赖属性:
internal class CategoriesService : ICategoryService
{
public ICategoriesRepository CategoriesRepository { get; set; }
public IWorkstationsRepository WorkstationsRepository { get; set; }
// No constructor injection. I am too lazy for that, so the above properties
// are auto-injected with my custom ninject injection heuristic.
public void ActivateCategory(int categoryId)
{
CategoriesRepository.FindOne(categoryId).IsActive = true;
}
}
服务的目标是从控制器和存储库中的消除业务逻辑。
3.的ViewModels
很酷的事情,你说,但原因是你为什么要建造起来的过问是我无法得到的东西。 我使用的是automapper(其可查询的扩展),这让我创造的观点是这样的:
比方说,我有需要一个视图 IEnumerable<TicketViewModel>
模型。 我要做的就是:
public class FooController : Controller
{
public IMappingEngine Mapping { get; set; } // Thing from automapper.
public ITicketsRepository TicketsRepository { get; set; }
public ViewResult Tickes()
{
return View(TicketsRepository.GetAllForToday().Project(Mapping)
.To<TicketViewModel>().ToArray();
}
}
而已。 简单的调用库,这使得对基础数据源调用(另一种模式。我不会写它,因为仅用于测试需要它的抽象。),这使得数据库调用(或任何你实现IDataSource<T>
Automapper automappically的映射Ticket
到TicketViewModel
和形式的数据库我retrive 只需要我的ViewModel列,其中包括在一个请求交叉表 。
结论
还有什么好说的更多,但我希望这会给你一些精神食粮。 我所使用的模式和程序是:
- Automapper(映射);
- Ninject(依赖注入);
- 存储库(数据访问);
- 数据源(从数据读取..以及..从数据源);
- 服务(数据交互);
- 的ViewModels(数据传输对象);
- 也许别的东西,我会编辑添加有关。
当我开始读您的文章,我想,也许你正在寻找的是固体原理的理解。 然后你通过提接口层和业务层结束。 有趣。
有很多文章庆祝固体和干的圣杯(很多不理解什么干倡导者真的建议)。 但在.NET世界的总体思路,是不是去自动生成的Page_Load在一个aspx并开始输入了所有的威利愿意不愿意,直到页面做的事情是应该做的。 MVC救援。
你说你有每个视图模型。 我会打电话的声音。 即使两个型号是相同的,他们只是平等的,不一样的。 例如:甲NewsItem不是EventItem。 如果你想在一个扩展,它不应该影响其他。
然后你继续说,你是生产的车型在视图模型本身。 这听起来倒退。 但是你说你为了保持你的控制器清洁这么做。 好! 什么是你的心态缺失,是服务。
什么,你想要做的是将实际执行任何种类的工作,到服务的所有代码。 服务可以基于一个方面,或上的特征或为什么不控制。 纵观现在一个web项目,我看到:VisitorService,NewsfeedService,CalendarService,CachingService,MainMenuService,HeaderService,FooterService等等等等,循环往复。
在这种情况下,控制器仅用于询问服务(或服务),执行一些工作,一个模型负责任。 然后将该模型转发到一个视图。
一旦你得到了“业务逻辑”到服务,您可以轻松地将IOC(控制反转),以您的项目如果让你快乐。 我没有投我的票上的IoC呢。 我有阴森恐怖的好处并不像做广告一样大,你可以无需代码膨胀是肯定的事情。 不过,国际奥委会可能会问你,你的代码三思。
关于国际奥委会很随和的教程,我建议Ninject。 它不仅配备了忍者,武士不过,剑和手里剑为好。 这比汽车和动物凉爽了不少。
https://github.com/ninject/ninject/wiki/Dependency-Injection-By-Hand
控制器:
从理论上讲控制器应该只处理“数据”。 移动信息从一个地方到另一个地方。
小例子:
- 控制器接收请求“的GetMessage”与一些参数。
- 发送该数据到服务层。 在服务层要访问存储库返回的消息。
- Cntroller接收该消息(或者,如果有没有空),并决定是否shoudl发送关于收到消息发回或也许有错误,用户应该以某种方式通知。
“在理论上”所有业务逻辑应该是背后的一些服务层。 这样,你可以easilly检验一切。 逻辑控制器使一些测试更困难。
接口:
接口为基础的设计现在很流行。 尤其是与所有的IoC容器处理扶养注射。 但是,如果你已经开始用这个概念并不理会这些关键字。 如果你知道Repository模式,然后尝试先用IRepository接口,而不是由具体类accesing仓库,使用IRepository。 (就在控制器与资源库的变化领域IRepository)。
Generaly关于接口
你会看到在更复杂的场景界面的好处,但有一个技术,它会告诉你这种方法的所有荣耀。 单元测试+嘲讽。