书接上文,上文写了个简单的.net core api程序创建流程,今天来写一下简单项目搭建步骤。
我们这里还是使用Autofac容器,具体使用教程可参考文章《.NET Core基础知识-依赖注入(Autofac)》这篇文章介绍的比较详细了。下面我说一下在.net core6里是怎么创建注入的。
#region Autofac程序集注入
//添加Autofac容器
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
//builder.Host.ConfigureContainer(container => { container.RegisterType().As(); });
//builder.Host.ConfigureContainer(container => { container.RegisterType().As(); });
//.net core6 Autofac程序集扫描注入
Assembly service = Assembly.Load("Services");
Assembly repository = Assembly.Load("Repositorys");
builder.Host.ConfigureContainer<ContainerBuilder>(container =>
{
container.RegisterAssemblyTypes(service, repository).Where(t => t.Name.EndsWith("Services"))
.AsImplementedInterfaces();
});
builder.Host.ConfigureContainer<ContainerBuilder>(container =>
{
container.RegisterAssemblyTypes(service, repository).Where(t => t.Name.EndsWith("Repositorys"))
.AsImplementedInterfaces();
});
//早期.net core Autofac程序集扫描注入
//public void ConfigureContainer(ContainerBuilder builder)
//{
// Assembly service = Assembly.Load("Services");
// Assembly repository = Assembly.Load("Repository");
// //containerBuilder.RegisterAssemblyTypes(service).AsImplementedInterfaces().InstancePerDependency();
// builder.RegisterAssemblyTypes(service, repository).Where(t => t.Name.EndsWith("Service"))
// .AsImplementedInterfaces();
// builder.RegisterAssemblyTypes(service, repository).Where(t => t.Name.EndsWith("Repository"))
// .AsImplementedInterfaces();
//}
#endregion
通过扫描程序集注入,我们可以达到避免一条一条注入的烦恼,这个功能也比较实用。
#region Freesql注入
Func<IServiceProvider, IFreeSql> fsqlFactory = r =>
{
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.SqlServer, r.GetService<IConfiguration>()["ConnectionStrings:CloudDB"])
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}"))//监听SQL语句
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
.Build();
return fsql;
};
builder.Services.AddSingleton<IFreeSql>(fsqlFactory);
#endregion
var app = builder.Build();
//在项目启动时,从容器中获取IFreeSql实例,并执行一些操作:同步表,种子数据,FluentAPI等
using (IServiceScope serviceScope = app.Services.CreateScope())
{
var fsql = serviceScope.ServiceProvider.GetRequiredService<IFreeSql>();
//fsql.CodeFirst.SyncStructure(typeof(Topic));//Topic 为要同步的实体类//同步实体类到数据库
}
数据库链接写在了appsettings.json中,注入的话可以直接抄官方文档
Func<IServiceProvider, IFreeSql> fsql = r =>
{
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=freedb.db")//@"Data Source=freedb.db"这里可以直接写数据库链接语句,如果想写在appsettings.json中的话,可以看下上面我的那种写法。
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}"))//监听SQL语句
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
.Build();
return fsql;
};
services.AddSingleton<IFreeSql>(fsql);
这一层就是实体类,我这里使用的是Freesql,实体类配置可查阅官方文档(也可以使用SQLSugar),这两种我比较常用。
这一层是用于数据处理,里面分两个文件夹,IRepositorys接口层和Repositorys实现层。具体用法如下:
//IRepositorys接口层
public interface ILoginRepositorys
{
Task<int> Login(string Account,string Password);
}
//Repositorys实现层
public class LoginRepositorys : ILoginRepositorys
{
private readonly IFreeSql _fsql;
public LoginRepositorys(IFreeSql fsql)
{
this._fsql = fsql;
}
//登录查询
public async Task<int> Login(string Account, string Password)
{
var curd = (await _fsql.Select<UserInfo>().Where(x => x.Account == Account && x.Password == Password).ToListAsync()).Count();
return curd;
}
}
这层就是来写业务了,里面也是分两个文件夹,IServices接口层和Services实现层。具体用法如下:
//IServices接口层
public interface ILoginServices
{
Task<int> Login(string Account, string Password);
}
//Services实现层
public class LoginServices : ILoginServices
{
private readonly ILoginRepositorys _loginRepositorys;
public LoginServices(ILoginRepositorys loginRepositorys)
{
this._loginRepositorys = loginRepositorys;
}
//登录查询
public async Task<int> Login(string Account, string Password)
{
int Msg = 0;
try
{
if (string.IsNullOrWhiteSpace(Account))
{
throw new Exception("账号不能为空!");
}
if (string.IsNullOrWhiteSpace(Password))
{
throw new Exception("密码不能为空!");
}
if (await _loginRepositorys.Login(Account,Password)> 0)
{
Msg = 1;
}
}
catch (Exception ex)
{
return Msg;
}
return Msg;
}
}
这里我们只需要做业务处理即可,如码所示,当我们处理业务时只需要调用LoginRepositorys层即可,这样充分展现了高内聚、低耦合的设计,而且后期易于维护,当数据库发生变化时,只需要修改LoginRepositorys层,就不用修改业务层了。
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly ILoginServices _loginServices;
public HomeController(ILoginServices loginServices)
{
this._loginServices = loginServices;
}
[HttpGet]
public string Word()
{
return "Hello Word!";
}
[HttpGet]
public string Login(string account, string password)
{
string Meg = "我是测试!";
if (account == "admin" && password == "123456")
{
Meg = "测试成功了!";
}
return Meg;
}
[HttpGet]
public async Task<int> Logins(string Account, string Password)
{
//使用MD5加密
string Passwords = MD5Helper.MD5Encrypt64(Password);
return (await _loginServices.Login(Account, Passwords));
}
}
主要思想:前端—>控制器层(API层)—>Services层—>LoginRepositorys层
目前是写了个比较简单的框架搭建Demo,后续会继续补充,也会继续开发别的框架Demo,学无止境!