# MasterChief **Repository Path**: xiaodelea/MasterChief ## Basic Information - **Project Name**: MasterChief - **Description**: C# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 3 - **Created**: 2019-10-29 - **Last Updated**: 2025-05-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README > C# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。 项目架构思维导图: ![设计](https://9o7amq.dm.files.1drv.com/y4mvdeFkWkSFrsbowcTYmKLg5_xMkv2M9_7S3HwyQp1lmvOWURZQnzQN18sMDcB-sGNRf4ZS-WqImDuOKY_1huI90ubUT8uf1oaFk0ojztU9xjId0pvhTnu0B6DcMD9JdDYVOHEgBoUq3U23QntnItai4eIqrTvtHr5bkwdrQjDqHZKp2FBs0Fuv25LT-z_iSONM8mdzBCeEXzGVl6xsiLLFQ?width=1140&height=510&cropmode=none) 目录 ================= * [1\. 数据库访问](#1-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BF%E9%97%AE) * [2\. 日志](#2-%E6%97%A5%E5%BF%97) * [3\. 缓存](#3-%E7%BC%93%E5%AD%98) * [4\. 配置](#4-%E9%85%8D%E7%BD%AE) * [5\. 验证码](#5-%E9%AA%8C%E8%AF%81%E7%A0%81) * [6\. 序列化与反序列化](#6-%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%8E%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96) * [7\. EXCEL导入导出](#7-excel%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA) * [8\. 文件下载](#8-%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD) #### 1. 数据库访问 --- a. 支持Dapper和Entity Framework 两种ORM框架; b. 通过IOC可以很少代码在Dapper和Entity Framework切换; c. 实现Repository和UnitOfWork; d. CURD以及事务实现简单,很大程度关注业务实现即可; 代码使用说明: 1. Create 添加 ```csharp public bool Create(EFSample samle) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Create(samle); } } ``` 2. Delete 删除 ```c# public bool Delete(EFSample sample) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Delete(sample); } } ``` 3. Update 修改 ```c# public bool Update(EFSample sample) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Update(sample); } } ``` 4. GetByKeyID 根据主键查询 ```csharp public EFSample GetByKeyID(Guid id) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetByKeyID(id); } } ``` 5. GetList 条件查询集合 ```c# public List GetList(Expression> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetList(predicate); } } ``` 6. Exist 条件查询是否存在 ```c# public bool Exist(Expression> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Exist(predicate); } } ``` 7. SqlQuery 执行Sql脚本 ```c# public List SqlQuery(string sql, DbParameter[] parameter) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.SqlQuery(sql, parameter)?.ToList(); } } ``` 8. CreateWithTransaction 事务处理 ```c# public bool CreateWithTransaction(EFSample sample, EFSample sample2) { bool result = true; using (IDbContext dbcontext = _contextFactory.Create()) { try { dbcontext.BeginTransaction();//开启事务 dbcontext.Create(sample); dbcontext.Create(sample2); dbcontext.Commit(); } catch (Exception) { dbcontext.Rollback(); result = false; } } return result; } ``` 9. GetFirstOrDefault 条件查询第一项或默认数据 ```c# public EFSample GetFirstOrDefault(Expression> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetFirstOrDefault(predicate); } } ``` 10. 单元测试以及Sql Server脚本 ```csharp using MasterChief.DotNet.Core.DapperTests; using MasterChief.DotNet.Core.DapperTests.Model; using MasterChief.DotNet.Core.DapperTests.Service; using MasterChief.DotNet4.Utilities.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Ninject; using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.Threading.Tasks; namespace MasterChief.DotNet.Core.Dapper.Tests { [TestClass()] public class SampleServiceTests { private IKernel _kernel = null; private ISampleService _sampleService = null; private readonly Guid _testID = "2F6D3C43-C2C7-4398-AD2B-ED5E82D78888".ToGuidOrDefault(Guid.Empty); private readonly string _testName = "DapperSample"; [TestInitialize] public void SetUp() { _kernel = new StandardKernel(new ServiceModule()); Assert.IsNotNull(_kernel); _sampleService = _kernel.Get(); if (!_sampleService.Exist(ent => ent.ID == _testID)) { _sampleService.Create(new EFSample() { UserName = _testName, ID = _testID }); } } /// /// 创建测试 /// [TestMethod()] public void CreateTest() { bool actual = _sampleService.Create(new EFSample() { UserName = "Dapper" + DateTime.Now.ToString("MMddHHmmss") }); Assert.IsTrue(actual); } [TestMethod()] public void GetFirstOrDefaultTest() { EFSample actual = _sampleService.GetFirstOrDefault(ent => ent.ID == _testID); Assert.IsNotNull(actual); } [TestMethod()] public void GetByKeyIdTest() { EFSample actual = _sampleService.GetByKeyID(_testID); Assert.IsNotNull(actual); } [TestMethod()] public void DeleteTest() { bool actual = _sampleService.Delete(new EFSample() { ID = _testID }); Assert.IsTrue(actual); } [TestMethod()] public void GetListTest() { List actual = _sampleService.GetList(ent => ent.Available == true); Assert.IsNotNull(actual); CollectionAssert.AllItemsAreNotNull(actual); } [TestMethod()] public void UpdateTest() { EFSample sample = new EFSample { ID = _testID, ModifyTime = DateTime.Now, UserName = "modify" }; bool actual = _sampleService.Update(sample); Assert.IsNotNull(actual); } [TestMethod()] public void TransactionSuccessTest() { EFSample sample = new EFSample { UserName = "TransactionSuccess1" }; EFSample sample2 = new EFSample { UserName = "TransactionSuccess2" }; bool actual = _sampleService.CreateWithTransaction(sample, sample2); Assert.IsTrue(actual); } [TestMethod()] public void TransactionFailTest() { EFSample sample3 = new EFSample { UserName = "TransactionSuccess3" }; EFSample sample4 = new EFSample { UserName = null }; bool actual = _sampleService.CreateWithTransaction(sample3, sample4); Assert.IsFalse(actual); } [TestMethod()] public void ExistTest() { bool actual = _sampleService.Exist(ent => ent.ID == _testID); Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.UserName == _testName); Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.CreateTime >= DateTime.Now.AddDays(-1)); Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.CreateTime <= DateTime.Now); Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.Available == true); Assert.IsTrue(actual); actual = _sampleService.Exist(ent => ent.Available != true); Assert.IsFalse(actual); } [TestMethod()] public void SqlQueryTest() { string sql = @"select * from [dbo].[EFSample] where CreateTime>=@CreateTime and Available=@Available order by CreateTime desc"; DbParameter[] parameter = { new SqlParameter(){ ParameterName="@CreateTime", Value=DateTime.Now.AddDays(-1) }, new SqlParameter(){ ParameterName="@Available", Value=true } }; List actual = _sampleService.SqlQuery(sql, parameter); Assert.IsNotNull(actual); CollectionAssert.AllItemsAreNotNull(actual); } /// /// 多线程测试 /// [TestMethod()] public void CreateTestThreadTest() { Task[] tasks = { Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), Task.Factory.StartNew(() => CreateTest()), }; Task.WaitAll(tasks); } } } ``` ```sql USE [Sample] GO /****** Object: Table [dbo].[EFSample] Script Date: 2019/3/9 22:04:45 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[EFSample]( [ID] [uniqueidentifier] NOT NULL, [CreateTime] [datetime] NOT NULL, [ModifyTime] [datetime] NOT NULL, [Available] [bit] NOT NULL, [UserName] [nvarchar](20) NOT NULL, CONSTRAINT [EFSamle_PK] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'EFSample', @level2type=N'COLUMN',@level2name=N'UserName' GO ``` #### 2. 日志 --- a. 目前实现基于Log4Net的本地文件日志以及Kafka ELK的日志; b. 基于接口ILogService可以很容易扩展其他日志显示; 代码使用说明 1. 配置依赖注入,日志实现方式,这里采用文件日志形式 ```c# using MasterChief.DotNet.Core.Log; using Ninject.Modules; namespace MasterChief.DotNet.Core.LogTests { public sealed class LogModule : NinjectModule { public override void Load() { Bind().To().InSingletonScope(); } } } ``` 2. 拷贝日志config文件到项目内,并设置属性“始终复制”到输出目录,您可以根据项目需求调整config内容 ```xml
``` 3. 单元测试 ```c# using MasterChief.DotNet.Core.LogTests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Ninject; namespace MasterChief.DotNet.Core.Log.Tests { [TestClass()] public class FileLogServiceTests { private IKernel _kernel = null; private ILogService _logService = null; [TestInitialize] public void SetUp() { _kernel = new StandardKernel(new LogModule()); Assert.IsNotNull(_kernel); _logService = _kernel.Get(); } [TestMethod()] public void DebugTest() { _logService.Debug("DebugTest"); } [TestMethod()] public void ErrorTest() { _logService.Error("ErrorTest"); } [TestMethod()] public void FatalTest() { _logService.Fatal("FatalTest"); } [TestMethod()] public void InfoTest() { _logService.Info("InfoTest"); } [TestMethod()] public void WarnTest() { _logService.Warn("WarnTest"); } } } ``` #### 3. 缓存 --- a. 支持本地内存缓存,HttpRequest请求缓存,Redis缓存; b. 基于ICacheProvider接口,可以很容易扩展其他缓存实现; 代码使用说明: 1. 配置依赖注入,缓存实现方式,这里采用LocalCacheProvider缓存实现; ```c# using MasterChief.DotNet.Core.Cache; using Ninject.Modules; namespace MasterChief.DotNet.Core.CacheTests { public sealed class CacheModule : NinjectModule { public override void Load() { Bind().To().InSingletonScope(); } } } ``` 2. 单元测试 ```c# using MasterChief.DotNet.Core.CacheTests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Ninject; namespace MasterChief.DotNet.Core.Cache.Tests { [TestClass()] public class LocalCacheProviderTests { private IKernel _kernel = null; private ICacheProvider _cacheProvider = null; private readonly string _testCacheKey = "sampleKey"; private readonly string _testCache = "sample"; private readonly string _testKeyFormat = "login_{0}"; [TestInitialize] public void SetUp() { _kernel = new StandardKernel(new CacheModule()); Assert.IsNotNull(_kernel); _cacheProvider = _kernel.Get(); _cacheProvider.Set(_testCacheKey, _testCache, 10); } [TestMethod()] public void GetTest() { string actual = _cacheProvider.Get(_testCacheKey); Assert.AreEqual(_testCache, actual); } [TestMethod()] public void IsSetTest() { bool actual = _cacheProvider.IsSet(_testCacheKey); Assert.IsTrue(actual); } [TestMethod()] public void RemoveTest() { _cacheProvider.Remove(_testCacheKey); bool actual = _cacheProvider.IsSet(_testCacheKey); Assert.IsFalse(actual); } [TestMethod()] public void RemoveByPatternTest() { string _loginKey = string.Format(_testKeyFormat, "123"); _cacheProvider.Set(_loginKey, _testCache, 10); bool actual = _cacheProvider.IsSet(_loginKey); Assert.IsTrue(actual); _cacheProvider.RemoveByPattern(_testKeyFormat); actual = _cacheProvider.IsSet(_loginKey); Assert.IsFalse(actual); actual = _cacheProvider.IsSet(_testCacheKey); Assert.IsTrue(actual); } [TestMethod()] public void SetTest() { _cacheProvider.Set("sampleSetKey", "sampleSetCache", 10); bool actual = _cacheProvider.IsSet("sampleSetKey"); Assert.IsTrue(actual); } } } ``` #### 4. 配置 --- a. 目前支持配置文件本地持久化,并且支持配置文件缓存依赖减少读取文件次数; b. 基于IConfigProvider接口,可以很容易扩展其他配置实现; 代码使用说明: 1. 配置依赖注入,配置实现方式,这里采用FileConfigProvider缓存实现; ```c# using MasterChief.DotNet.Core.Config; using Ninject.Modules; namespace MasterChief.DotNet.Core.ConfigTests { public sealed class ConfigModule : NinjectModule { public override void Load() { Bind().To().InSingletonScope(); // Bind().ToSelf().InSingletonScope(); Bind().To().InSingletonScope(); } } } ``` 2. 扩展配置上下文基于文件依赖 ```c# using MasterChief.DotNet.Core.Config; using MasterChief.DotNet4.Utilities.WebForm.Core; using System; using System.Web.Caching; namespace MasterChief.DotNet.Core.ConfigTests { public sealed class CacheConfigContext : ConfigContext { public override T Get(string index = null) { if (!(base.ConfigService is FileConfigService)) { throw new NotSupportedException("CacheConfigContext"); } string filePath = GetClusteredIndex(index); string key = filePath; object cacheContent = CacheManger.Get(key); if (cacheContent != null) { return (T)cacheContent; } T value = base.Get(index); CacheManger.Set(key, value, new CacheDependency(filePath)); return value; } } } ``` 3. 单元测试 ```c# using MasterChief.DotNet.Core.ConfigTests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Ninject; using System.Collections.Generic; namespace MasterChief.DotNet.Core.Config.Tests { [TestClass()] public class FileConfigServiceTests { private IKernel _kernel = null; private IConfigProvider _configProvider = null; public ConfigContext _configContext = null; [TestInitialize] public void SetUp() { _kernel = new StandardKernel(new ConfigModule()); Assert.IsNotNull(_kernel); _configProvider = _kernel.Get(); _configContext = _kernel.Get(); } [TestMethod()] public void SaveConfigTest() { RedisConfig redisConfig = new RedisConfig { AutoStart = true, LocalCacheTime = 10, MaxReadPoolSize = 1024, MaxWritePoolSize = 1024, ReadServerList = "10", RecordeLog = true, WriteServerList = "10" }; redisConfig.RedisItems = new List { new RedisItemConfig() { Text = "MasterChief" }, new RedisItemConfig() { Text = "Config." } }; _configContext.Save(redisConfig, "prod"); _configContext.Save(redisConfig, "alpha"); RedisConfig prodRedisConfig = _configContext.Get("prod"); Assert.IsNotNull(prodRedisConfig); prodRedisConfig = _configContext.Get("prod");//文件缓存测试 Assert.IsNotNull(prodRedisConfig); RedisConfig alphaRedisConfig = _configContext.Get("alpha"); Assert.IsNotNull(alphaRedisConfig); DaoConfig daoConfig = new DaoConfig { Log = "server=localhost;database=Sample;uid=sa;pwd=sasa" }; _configContext.Save(daoConfig, "prod"); _configContext.Save(daoConfig, "alpha"); DaoConfig prodDaoConfig = _configContext.Get("prod"); Assert.IsNotNull(prodDaoConfig); DaoConfig alphaDaoConfig = _configContext.Get("alpha"); Assert.IsNotNull(alphaDaoConfig); } } } ``` 4. 本地配置会在程序根目录Config下,如图: ![1552231625890](https://8y6yzw.dm.files.1drv.com/y4mibGGlIfda5MwK941vhcR5zHNBGgF1UEQAjozRAJHrcAF4wr6PpkKwY4uQyLVTYIjUTcEeje88BJzOhIdPACqtDMsfWQw22v6sxy8jU4tLLF3FOpe_oZlVol4ieeiRPa_wWUIfY_5TwRzQ1eOze0EpocLrxks30kcg73LZD8P-XJR5hH0fujGPqBP0cyw5KmG-s5maLn9a-ODDEZf-LxmmQ?width=607&height=147&cropmode=none) 5. 配置文件基于XML持久化存储,如图: ![1552231725395](https://8y5n3a.dm.files.1drv.com/y4mqjcZUrUGGJzfE_S09gBfz-ZrWnH7vfrzxBbIb922zzqP7PU5ae5f7HgZk49_SfqZE8U3YY3H0Fn9WddI1oXRSAU9vBMcrlxX4FrXUzHBaJq9s5E8TEvaSsv-4ATHsLkHZfdttbF7h02Fo5451D2uwtxASSh8TPxrCAuJ9byRmD6qOeKYM1Kh9ZoV1HMaIVwdFF5MeS5KZ-LultAHCOvWFw?width=1155&height=235&cropmode=none) #### 5. 验证码 --- a. 派生实现ValidateCodeType抽象类,来自定义验证码样式; b. 派生实现VerifyCodeHandler抽象类,快速切换需要显示验证码; 代码使用说明: 1. Mvc 简单使用如下: ```c# /// /// 处理生成Mvc 程序验证码 /// public sealed class MvcVerifyCodeHandler : VerifyCodeHandler { public override void OnValidateCodeCreated(HttpContext context, string validateCode) { context.Session["validateCode"] = validateCode; } public override byte[] CreateValidateCode(string style) { ValidateCodeType createCode; switch (style) { case "type1": createCode = new ValidateCode_Style1(); break; default: createCode = new ValidateCode_Style1(); break; } var buffer = createCode.CreateImage(out var validateCode); OnValidateCodeCreated(HttpContext.Current, validateCode); return buffer; } } ``` 2. WebForm 简单使用如下: ```c# /// /// WebFormVerifyCodeHandler 的摘要说明 /// public class WebFormVerifyCodeHandler : VerifyCodeHandler, IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { var validateType = context.Request.Params["style"]; var buffer = CreateValidateCode(validateType); context.Response.ClearContent(); context.Response.ContentType = MimeTypes.ImageGif; context.Response.BinaryWrite(buffer); } public bool IsReusable => false; public override void OnValidateCodeCreated(HttpContext context, string validateCode) { context.Session["validateCode"] = validateCode; } public override byte[] CreateValidateCode(string style) { style = style?.Trim(); ValidateCodeType createCode; switch (style) { case "type1": createCode = new ValidateCode_Style1(); break; default: createCode = new ValidateCode_Style1(); break; } var buffer = createCode.CreateImage(out var validateCode); OnValidateCodeCreated(HttpContext.Current, validateCode); return buffer; } } ``` #### 6. 序列化与反序列化 --- a. 目前支持Json以及Protobuf两种方式的序列化与反序列化 b. 可以通过实现接口ISerializer扩展实现其他方式; 代码使用说明: ```c# private static void Main() { SampleSerializer(new JsonSerializer()); Console.WriteLine(Environment.NewLine); SampleSerializer(new ProtocolBufferSerializer()); Console.ReadLine(); } private static void SampleSerializer(ISerializer serializer) { #region 单个对象序列化与反序列化 var person = new Person(); person.Age = 10; person.FirstName = "yan"; person.LastName = "zhiwei"; person.Remark = "ISerializer Sample"; var jsonText = serializer.Serialize(person); Console.WriteLine($"{serializer.GetType().Name}-Serialize" + jsonText); var getPerson = serializer.Deserialize(jsonText); Console.WriteLine($"{serializer.GetType().Name}-Deserialize" + getPerson); #endregion #region 集合序列化与反序列化 var persons = new List(); for (var i = 0; i < 10; i++) persons.Add(new Person { FirstName = "Yan", Age = 20 + i, LastName = "Zhiwei", Remark = DateTime.Now.ToString(CultureInfo.InvariantCulture) }); jsonText = serializer.Serialize(persons); Console.WriteLine($"{serializer.GetType().Name}-Serialize" + jsonText); var getPersons = serializer.Deserialize>(jsonText); foreach (var item in getPersons) Console.WriteLine($"{serializer.GetType().Name}-Deserialize" + item); #endregion } ``` ![](https://846dvq.dm.files.1drv.com/y4mWYJTjMj8XnRRQEUW4U1zgKNRGIVbY_CKcJS0hUipY_ydHAEYW8pW-xc8Bkj0BnF6k4SdJDrPeSxDLx3UcNq-xliJk6N5OyJ3fTJ00nBFuf2wcg_esB8CggR2jwHYgBbvcYGappUbqG4aqi3-sd4e8PAKyRv6DkjmnjPo-B0xX7QaHgbV_kg0YLlhj5_BTHG83qwrk2TfVGkGROnDZMk1Zw?width=960&height=639&cropmode=none) #### 7. EXCEL导入导出 --- a. 基于Npoi实现,可以基于接口IExcelManger扩展实现诸如MyXls等; b. 目前实现了将Excel导出DataTable和DataTable导出到Excel文件; c. 后续完善诸如整个Excel文件导入导出等; 代码使用说明: 1. 将DataTable导出到Excel文件 ```c# private void BtnToExcel_Click(object sender, EventArgs e) { var mockTable = BuilderExcelData(); _mockExcelPath = $"D:\\ExcelSample{DateTime.Now.FormatDate(12)}.xls"; _excelManger.ToExcel(mockTable, "员工信息汇总", "员工列表", _mockExcelPath); Process.Start(_mockExcelPath); } private DataTable BuilderExcelData() { var mockTable = new DataTable(); mockTable.Columns.Add(new DataColumn {ColumnName = "序号"}); mockTable.Columns.Add(new DataColumn {ColumnName = "姓名"}); mockTable.Columns.Add(new DataColumn {ColumnName = "工作单位"}); mockTable.Columns.Add(new DataColumn {ColumnName = "性别"}); mockTable.Columns.Add(new DataColumn {ColumnName = "入职时间"}); for (var i = 0; i < 100; i++) mockTable.Rows.Add(i.ToString(), $"张{i}", $"李{i}计算机公司", i % 2 == 0 ? "男" : "女", DateTime.Now.AddDays(i)); return mockTable; } ``` ![](https://845n1a.dm.files.1drv.com/y4mfwfj5Ba0Y2KQLZoyW7I8f1mw5Z2m6KuAIyOiNPiVwzFMtqXPrHGQ2sCa3Ugl0OpcV-Tr0Y1Qbcf009TqtkwLQPcmaAg0Y7jM5guS7e9GYC_mbPLnBUgxxob4IbYrVoxxGh_Vfad2nwRX0wmI1clxx1cgFd4Xpoc_clXpOjJ8zZ1zj4Q_099E6Sk2ucuzpXJt3KRzYlo1TgCtotELq1roDg?width=745&height=982&cropmode=none) 2. 将Excel文件导出DataTable ```c# private void BtnToDataTable_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(_mockExcelPath)) { MessageBox.Show("请生成模拟测试EXCEL文件"); return; } var excleTable = _excelManger.ToDataTable(_mockExcelPath, 0, 1, 2); var jsonText = _jsonSerializer.Serialize(excleTable); MessageBox.Show(jsonText); } ``` #### 8. 文件下载 --- a.支持下载文件加密; b.支持下载自定义限速; c.通过DownloadHandler抽象类实现扩展诸如在Asp.Net Mvc实现; 代码使用说明: 1. 文件下载配置文件 ```xml ``` 2. 在WebForm实现DownloadHandler抽象类,迅速实现文件下载 ```c# public class FileDownloadHandler : DownloadHandler, IHttpHandler { public void ProcessRequest(HttpContext context) { var fileName = context.Request["fileName"]; StartDownloading(context, fileName); } public bool IsReusable => false; public override void OnDownloadFailed(HttpContext context, string fileName, string filePath, string ex) { context.Response.Write(ex); } public override void OnDownloadSucceed(HttpContext context, string fileName, string filePath) { var result = $"文件[{fileName}]下载成功,映射路径:{filePath}"; context.Response.Write(result); } } ``` 3. 修改Web.Config 文件 ```xml ```