前言
大家好,我依旧是你们的老朋友Rector,很高兴又在周五的时候准时和大家见面。
Rector的系列文章【一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]】从写作以来,已经出了六期了,其中受到了很多朋友的喜欢,在此非常感谢大家对Rector的支持,也希望Rector的文章可以帮助大家(特别是才接触或者是对.NET/C#高级编程比较薄弱的朋友们)在.NET/C#的开发之旅中更快地提升自己的开发技巧和经验。
上一篇《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](六)》我们对TsBlog应用程序的仓储层进行了一次重大的重构,即:使用泛型仓储将通用的数据库操作进行了封装,让我们在创建仓储层接口和实现的时候能精简重复的代码,今天要给大家分享的是对服务层的泛型封装和重构,实现原理大致与仓储层相似。
本文知识要点
- 泛型服务层的封装与重构
重构服务层
提取泛型服务基类
打开项目【TsBlog.Services】,创建 服务层通用接口类 IService.cs,在其中创建服务层通用的接口方法,如下:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace TsBlog.Services
{
///
/// 服务接口
///
///
public interface IService
{
///
/// 根据主值查询单条数据
///
/// 主键值
/// 泛型实体
T FindById(object pkValue);
///
/// 查询所有数据(无分页,请慎用)
///
///
IEnumerable FindAll();
///
/// 根据条件查询数据
///
/// 条件表达式树
/// 排序
/// 泛型实体集合
IEnumerable FindListByClause(Expression> predicate, string orderBy);
///
/// 根据条件查询数据
///
/// 条件表达式树
///
T FindByClause(Expression> predicate);
///
/// 写入实体数据
///
/// 实体类
///
long Insert(T entity);
///
/// 更新实体数据
///
///
///
bool Update(T entity);
///
/// 删除数据
///
/// 实体类
///
bool Delete(T entity);
///
/// 删除数据
///
/// 过滤条件
///
bool Delete(Expression> @where);
///
/// 删除指定ID的数据
///
///
///
bool DeleteById(object id);
///
/// 删除指定ID集合的数据(批量删除)
///
///
///
bool DeleteByIds(object[] ids);
}
}
再创建 泛型基类 GenericService.cs,在其中创建服务层通用的方法,如下:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using TsBlog.Repositories;
namespace TsBlog.Services
{
public abstract class GenericService : IService, IDependency where T : class, new()
{
private readonly IRepository _repository;
protected GenericService(IRepository repository)
{
_repository = repository;
}
///
/// 根据主值查询单条数据
///
/// 主键值
/// 泛型实体
public T FindById(object pkValue)
{
return _repository.FindById(pkValue);
}
///
/// 查询所有数据(无分页,请慎用)
///
///
public IEnumerable FindAll()
{
return _repository.FindAll();
}
///
/// 根据条件查询数据
///
/// 条件表达式树
/// 排序
/// 泛型实体集合
public IEnumerable FindListByClause(Expression> predicate, string orderBy)
{
return _repository.FindListByClause(predicate, orderBy);
}
///
/// 根据条件查询数据
///
/// 条件表达式树
///
public T FindByClause(Expression> predicate)
{
return _repository.FindByClause(predicate);
}
///
/// 写入实体数据
///
/// 实体类
///
public long Insert(T entity)
{
return _repository.Insert(entity);
}
///
/// 更新实体数据
///
///
///
public bool Update(T entity)
{
return _repository.Update(entity);
}
///
/// 删除数据
///
/// 实体类
///
public bool Delete(T entity)
{
return _repository.Delete(entity);
}
///
/// 删除数据
///
/// 过滤条件
///
public bool Delete(Expression> @where)
{
return _repository.Delete(@where);
}
///
/// 删除指定ID的数据
///
///
///
public bool DeleteById(object id)
{
return _repository.DeleteById(id);
}
///
/// 删除指定ID集合的数据(批量删除)
///
///
///
public bool DeleteByIds(object[] ids)
{
return _repository.DeleteByIds(ids);
}
}
}
精简并修改 IPostService.cs:
using TsBlog.Domain.Entities;
using TsBlog.Repositories;
namespace TsBlog.Services
{
public interface IPostService : IDependency, IService
{
}
}
再精简并修改 PostService.cs:
using TsBlog.Domain.Entities;
using TsBlog.Repositories;
namespace TsBlog.Services
{
public class PostService : GenericService, IPostService
{
private readonly IPostRepository _repository;
public PostService(IPostRepository repository) : base(repository)
{
_repository = repository;
}
}
}
重新编译并按F5运行 【TsBlog.Frontend】Web应用程序,你会看到如下的错误提示:
这是为什么呢?是因为我们之前写好的 PostRepository.cs类中没有继承IPostRepository接口,但我们在 PostService.cs 类中使用了非泛型的 IPostRepository接口,所以在 PostRepository.cs 类中添加 IPostRepository 的接口,此时的 PostRepository.cs :
using TsBlog.Domain.Entities;
namespace TsBlog.Repositories
{
///
/// POST表的数据库操作类
///
public class PostRepository : GenericRepository, IPostRepository
{
}
}
最终的 Global.asax.cs :
using Autofac;
using Autofac.Features.ResolveAnything;
using Autofac.Integration.Mvc;
using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using TsBlog.AutoMapperConfig;
using TsBlog.Repositories;
namespace TsBlog.Frontend
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
//BundleConfig.RegisterBundles(BundleTable.Bundles);
AutofacRegister();
AutoMapperRegister();
}
private void AutofacRegister()
{
var builder = new ContainerBuilder();
//注册MvcApplication程序集中所有的控制器
builder.RegisterControllers(typeof(MvcApplication).Assembly);
//注册仓储层服务
//builder.RegisterType().As();
//注册基于接口约束的实体
var assembly = AppDomain.CurrentDomain.GetAssemblies();
builder.RegisterAssemblyTypes(assembly)
.Where(
t => t.GetInterfaces()
.Any(i => i.IsAssignableFrom(typeof(IDependency)))
)
.AsImplementedInterfaces()
.InstancePerDependency();
//builder.RegisterGeneric(typeof(GenericRepository<>))
// .As(typeof(IRepository<>));
//builder.RegisterGeneric(typeof(GenericService<>))
// .As(typeof(IService<>));
//builder.RegisterGeneric(typeof(GenericRepository<>));
//builder.RegisterGeneric(typeof(GenericService<>));
//注册服务层服务
//builder.RegisterType().As();
//注册过滤器
builder.RegisterFilterProvider();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
//设置依赖注入解析器
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
///
/// AutoMapper的配置初始化
///
private void AutoMapperRegister()
{
new AutoMapperStartupTask().Execute();
}
}
}
再次按F5运行,打开页面[http://localhost:54739/home/post ],页面又回来了,哈哈。。。
本文的源码托管地址:https://github.com/lampo1024/...
本文学习到此结束,本系列未完待续,我们下期再见……
如果你喜欢Rector的本系列文章,请为我点个大大的赞。
如果遇到问题,欢迎加入码友网官方QQ群:483350228
本文来源 码友网 《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](七)》