1 Core.Configuration.CommonConfig
namespace Core.Configuration
{
/// <summary>
/// 【常规配置--类】
/// <remarks>
/// 摘要:
/// 通过该类中的属性成员实例对“appsettings.json”文件中的常规配置相关等数据进行设定性读写操作。
/// 说明:
/// 属性成员的名称必须与JSON键/值对中的键相同,且属性成员的个数与键的个数也必须相等,
/// 否则ConfigurationBinder.Bind方法将不支持通过“appsettings.json”文件中数据库连接相关数据与当前类中的属性成员实例的设定性读写操作。
/// </remarks>
/// </summary>
public class CommonConfig : IConfig
{
/// <summary>
/// 【包含Autofac依赖注入容器?】
/// <remarks>
/// 摘要:
/// 获取/设置1个值false(默认值:不包含)/true(包含),该值指示是否把第3方Autofac依赖注入容器成到当前程序的.NetCore内置依赖注入容器。
/// </remarks>
/// </summary>
public bool UseAutofac { get; set; } = false;
}
}
2 Services.Installation.IInstallationService
namespace Services.Installation
{
/// <summary>
/// 【初始化安装服务--接口】
/// <remarks>
/// 摘要:
/// 继承于该接口的具体实现类在CodeFirst模式下,在执行当前程序的初始化安装时,把当前程序所必要的数据持久化到相应的表中。
/// </remarks>
/// </summary>
public interface IInstallationService
{
/// <param name="defaultUserEmail">默认的用户或电子邮箱。</param>
/// <param name="defaultUserPassword">默认用户或电子邮箱对应的密码。</param>
/// <summary>
/// 【异步初始化必要数据】
/// <remarks>
/// 摘要:
/// 在执行当前程序的初始化安装时,把当前程序所必要的数据持久化到相应的表中。
/// </remarks>
/// </summary>
Task InstallRequiredDataAsync(string defaultUserEmail, string defaultUserPassword);
}
}
3 Services.Installation.InstallationService
using Core.Caching;
using Core.Domain.Customers;
using Data;
namespace Services.Installation
{
/// <summary>
/// 【初始化安装服务--类】
/// <remarks>
/// 摘要:
/// 在CodeFirst模式下,在执行当前程序的初始化安装时,把当前程序所必要的数据持久化到相应的表中。
/// </remarks>
/// </summary>
public class InstallationService: IInstallationService
{
#region 拷贝构造方法与变量
private readonly IRepository<Customer> _customerRepository;
private readonly IRepository<Role> _roleRepository;
private readonly IRepository<CustomerRole> _customerRoleRepository;
private readonly IStaticCacheManager _staticCacheManager;
/// <summary>
/// 【拷贝构建方法】
/// <remarks>
/// 摘要:
/// 依赖注入容器通过拷贝构造方法,实例化该类中的变量成员。
/// </remarks>
/// </summary>
public InstallationService(IRepository<Customer> customerRepository,
IRepository<Role> roleRepository,
IRepository<CustomerRole> customerRoleRepository,
IStaticCacheManager staticCacheManager)
{
_customerRepository = customerRepository;
_roleRepository = roleRepository;
_customerRoleRepository = customerRoleRepository;
_staticCacheManager = staticCacheManager;
}
#endregion
#region 方法--私有/保护
#region 用户和客户初始化安装
/// <param name="defaultUserEmail">默认的用户或电子邮箱。</param>
/// <param name="defaultUserPassword">默认用户或电子邮箱对应的密码。</param>
/// <summary>
/// 【异步初始化安装用户和客户】
/// <remarks>
/// 摘要:
/// 在执行当前程序的初始化安装时,把必要的角色实例和默认用户实例持久化到角色表、用户表和用户角色映射表中。
/// </remarks>
/// </summary>
protected virtual async Task InstallCustomersAndUsersAsync(string defaultUserEmail, string defaultUserPassword)
{
var roleList = new List<Role>
{
new Role
{
Name = "Administrators",
Active = true,
IsSystemRole = true,
Remark = "管理员",
},
new Role
{
Name = "Registered",
Active = true,
IsSystemRole = true,
Remark = "游客(未注册用户)",
},
new Role
{
Name = "ForumModerators",
Active = true,
IsSystemRole = true,
Remark = "论坛主持人",
},
new Role
{
Name = "Vendors",
Active = true,
IsSystemRole = true,
Remark = "生产商(1个指定商品的生产商)",
},
new Role
{
Name = "Guests",
Active = true,
IsSystemRole = true,
Remark = "游客(未注册用户)",
},
};
await _roleRepository.InsertAsync(roleList);
var customerList = new List<Customer>
{
new Customer
{
Username = "Test",
Email = "Test@yourStore.com",
Avatar="/images/Avatar/子鼠Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
new Customer
{
Username = "Test_1",
Email = "Test_1@yourStore.com",
Avatar="/images/Avatar/丑牛Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
new Customer
{
Username = "Test_2",
Email = "Test_2@yourStore.com",
Avatar="/images/Avatar/寅虎Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
new Customer
{
Username = "Test_3",
Email = "Test_3@yourStore.com",
Avatar="/images/Avatar/卯兔Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
new Customer
{
Username = "Test_4",
Email = "Test_4@yourStore.com",
Avatar="/images/Avatar/辰龙Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
new Customer
{
Username = "Test_5",
Email = "Test_5@yourStore.com",
Avatar="/images/Avatar/巳蛇Mecha.png",
IsSystemAccount= true,
Active = true,
Deleted = false,
CreatedDate = DateTime.Now,
},
};
await _customerRepository.InsertAsync(customerList);
List<CustomerRole> customerRoleList = new List<CustomerRole>();
foreach (var item in customerList)
{
if (item.Email.Equals("Test@yourStore.com"))
{
foreach(var role in roleList)
{
customerRoleList.Add(new CustomerRole { CustomerId =item.Id, RoleId=role.Id });
}
}
else
{
customerRoleList.Add(new CustomerRole { CustomerId = item.Id, RoleId = roleList.Where(r => r.Name == "Registered").FirstOrDefault().Id });
}
}
await _customerRoleRepository.InsertAsync(customerRoleList);
}
#endregion
#endregion
#region 方法--接口实现
/// <param name="defaultUserEmail">默认的用户或电子邮箱。</param>
/// <param name="defaultUserPassword">默认用户或电子邮箱对应的密码。</param>
/// <summary>
/// 【异步初始化必要数据】
/// <remarks>
/// 摘要:
/// 在执行当前程序的初始化安装时,把当前程序所必要的数据持久化到相应的表中。
/// </remarks>
/// </summary>
public virtual async Task InstallRequiredDataAsync(string defaultUserEmail, string defaultUserPassword)
{
await InstallCustomersAndUsersAsync(defaultUserEmail, defaultUserPassword);
}
#endregion
}
}
4 Framework.Infrastructure.LazyInstance<T>
using Core.Infrastructure;
namespace Framework.Infrastructure
{
/// <typeparam name = "T"> 泛型类型实例(1个指定类的类型实例)。</typeparam>
/// <summary>
/// 【单例--类】
/// <remarks>
/// 摘要:
/// 以泛型形式,对1个指定类的类型实例进行懒加载操作。
/// </remarks>
/// </summary>
public class LazyInstance<T> : Lazy<T> where T : class
{
public LazyInstance(): base(() => EngineContext.Current.Resolve<T>())
{
}
}
}
5 重构Framework.Infrastructure.DIStartup.ConfigureServices
//初始化安装服务相关定义实例的依赖注入。
services.AddScoped<IInstallationService, InstallationService>();
//把Lazy泛型实例,注入到.NetCore内置依赖注入容器中。
var useAutofac = appSettings.Get<CommonConfig>().UseAutofac;
if (!useAutofac)
services.AddScoped(typeof(Lazy<>), typeof(LazyInstance<>));
6 重构Web.Controllers.InstallRefactoringController.DatabaseCreate
public async Task<IActionResult> DatabaseCreate()
{
string _message =string.Empty;
if (!DataSettingsManager.IsCurrentConnectionString())
{
DataSettingsManager.SaveSettings(new DataConfig
{
DataProvider = DataProviderType.SqlServer,
ConnectionString = "Data Source=.;Initial Catalog=ShopRazor;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True"
}, _fileProvider);
}
if (!await DataSettingsManager.CreateDatabaseAsync())
{
_message = "未能通过“EntityFrameworkCore”中间件已经在“Microsoft SQL Server”数据库软件中成功生成了指定数据库及其表。";
}
else
{
//自动生成数据库的同时把必要数据持久化到指定表中,只能使用“EngineContext.Current.Resolve”,
//而不能通过当前类的构造方法来实例化“IInstallationService”实例,因为构造方法不能实例化没有连接字符串的“EFCore”中间件。
var install = EngineContext.Current.Resolve<Lazy<IInstallationService>>();
await install.Value.InstallRequiredDataAsync("", "");
_message = "持久化生成或覆盖数据库连接字符串,并以Code-First方式创建数据库。";
}
return RedirectToAction("index", new { message = _message });
}
对以上功能更为具体实现和注释见230601_020ShopRazor(自动生成数据库的同时把必要数据持久化到指定表中)。