C# 開發輔助類庫,和士官長同樣身經百戰且越戰越勇的戰爭機器,能力無人能出其右。
GitHub:MasterChief 歡迎Star,歡迎Issues;
項目架構思惟導圖:git
a. 支持Dapper和Entity Framework 兩種ORM框架;github
b. 經過IOC能夠不多代碼在Dapper和Entity Framework切換;web
c. 實現Repository和UnitOfWork;redis
d. CURD以及事務實現簡單,很大程度關注業務實現便可;sql
代碼使用說明:數據庫
public bool Create(EFSample samle) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Create<EFSample>(samle); } }
public bool Delete(EFSample sample) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Delete(sample); } }
public bool Update(EFSample sample) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Update(sample); } }
public EFSample GetByKeyID(Guid id) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetByKeyID<EFSample>(id); } }
public List<EFSample> GetList(Expression<Func<EFSample, bool>> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetList<EFSample>(predicate); } }
public bool Exist(Expression<Func<EFSample, bool>> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.Exist<EFSample>(predicate); } }
public List<EFSample> SqlQuery(string sql, DbParameter[] parameter) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.SqlQuery<EFSample>(sql, parameter)?.ToList(); } }
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; }
public EFSample GetFirstOrDefault(Expression<Func<EFSample, bool>> predicate = null) { using (IDbContext dbcontext = _contextFactory.Create()) { return dbcontext.GetFirstOrDefault<EFSample>(predicate); } }
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<ISampleService>(); if (!_sampleService.Exist(ent => ent.ID == _testID)) { _sampleService.Create(new EFSample() { UserName = _testName, ID = _testID }); } } /// <summary> /// 建立測試 /// </summary> [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<EFSample> 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<EFSample> actual = _sampleService.SqlQuery(sql, parameter); Assert.IsNotNull(actual); CollectionAssert.AllItemsAreNotNull(actual); } /// <summary> /// 多線程測試 /// </summary> [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); } } }
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
a. 目前實現基於Log4Net的本地文件日誌以及Kafka ELK的日誌;json
b. 基於接口ILogService能夠很容易擴展其餘日誌顯示;c#
代碼使用說明緩存
using MasterChief.DotNet.Core.Log; using Ninject.Modules; namespace MasterChief.DotNet.Core.LogTests { public sealed class LogModule : NinjectModule { public override void Load() { Bind<ILogService>().To<FileLogService>().InSingletonScope(); } } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" /> </configSections> <log4net> <!-- FileLogger --> <logger name="FATAL_FileLogger"> <level value="ALL" /> <appender-ref ref="FATAL_FileAppender" /> </logger> <logger name="ERROR_FileLogger"> <level value="ALL" /> <appender-ref ref="ERROR_FileAppender" /> </logger> <logger name="WARN_FileLogger"> <level value="ALL" /> <appender-ref ref="WARN_FileAppender" /> </logger> <logger name="INFO_FileLogger"> <level value="ALL" /> <appender-ref ref="INFO_FileAppender" /> </logger> <logger name="DEBUG_FileLogger"> <level value="ALL" /> <appender-ref ref="DEBUG_FileAppender" /> </logger> <!-- AdoNetLogger --> <!--<logger name="AdoNetLogger"> <level value="ALL" /> <appender-ref ref="AdoNetAppender" /> </logger>--> <!-- ConsoleLogger --> <logger name="ConsoleLogger"> <level value="ALL" /> <appender-ref ref="ColoredConsoleAppender" /> </logger> <!--使用Rolling方式記錄日誌按照日來記錄日誌--> <appender name="FATAL_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\FATAL\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="ERROR_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\ERROR\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="WARN_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\WARN\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="INFO_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\INFO\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="DEBUG_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\DEBUG\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <!--使用AdoNetAppender方式記錄日誌按照日來記錄日誌--> <!--<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="1" /> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <connectionString value="DATABASE=Sample;SERVER=.\SQLEXPRESS;UID=sa;PWD=sasa;Connect Timeout=15;" /> <commandText value="INSERT INTO [Log4Net] ([Date],[Host],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @host, @thread, @log_level, @logger, @message, @exception)" /> <parameter> <parameterName value="@log_date" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%thread" /> </layout> </parameter> <parameter> <parameterName value="@host" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%property{log4net:HostName}" /> </layout> </parameter> <parameter> <parameterName value="@log_level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> <parameter> <parameterName value="@exception" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.ExceptionLayout" /> </parameter> </appender>--> <!--使用ConsoleAppender方式記錄日誌按照日來記錄日誌--> <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <mapping> <level value="INFO" /> <foreColor value="White, HighIntensity" /> <backColor value="Green" /> </mapping> <mapping> <level value="DEBUG" /> <foreColor value="White, HighIntensity" /> <backColor value="Blue" /> </mapping> <mapping> <level value="WARN" /> <foreColor value="Yellow, HighIntensity" /> <backColor value="Purple" /> </mapping> <mapping> <level value="ERROR" /> <foreColor value="Yellow, HighIntensity" /> <backColor value="Red" /> </mapping> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level%newline事件來源:%logger%newline事件行號:%line%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="UdpAppender" type="log4net.Appender.UdpAppender"> <remoteAddress value="127.0.0.1" /> <remotePort value="7071" /> <layout type="log4net.Layout.XmlLayoutSchemaLog4j" /> </appender> <root> <appender-ref ref="UdpAppender" /> </root> </log4net> </configuration>
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<ILogService>(); } [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"); } } }
a. 支持本地內存緩存,HttpRequest請求緩存,Redis緩存;多線程
b. 基於ICacheProvider接口,能夠很容易擴展其餘緩存實現;
代碼使用說明:
配置依賴注入,緩存實現方式,這裏採用LocalCacheProvider緩存實現;
using MasterChief.DotNet.Core.Cache; using Ninject.Modules; namespace MasterChief.DotNet.Core.CacheTests { public sealed class CacheModule : NinjectModule { public override void Load() { Bind<ICacheProvider>().To<LocalCacheProvider>().InSingletonScope(); } } }
單元測試
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<ICacheProvider>(); _cacheProvider.Set(_testCacheKey, _testCache, 10); } [TestMethod()] public void GetTest() { string actual = _cacheProvider.Get<string>(_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); } } }
a. 目前支持配置文件本地持久化,而且支持配置文件緩存依賴減小讀取文件次數;
b. 基於IConfigProvider接口,能夠很容易擴展其餘配置實現;
代碼使用說明:
配置依賴注入,配置實現方式,這裏採用FileConfigProvider緩存實現;
using MasterChief.DotNet.Core.Config; using Ninject.Modules; namespace MasterChief.DotNet.Core.ConfigTests { public sealed class ConfigModule : NinjectModule { public override void Load() { Bind<IConfigProvider>().To<FileConfigService>().InSingletonScope(); // Bind<ConfigContext>().ToSelf().InSingletonScope(); Bind<ConfigContext>().To<CacheConfigContext>().InSingletonScope(); } } }
擴展配置上下文基於文件依賴
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<T>(string index = null) { if (!(base.ConfigService is FileConfigService)) { throw new NotSupportedException("CacheConfigContext"); } string filePath = GetClusteredIndex<T>(index); string key = filePath; object cacheContent = CacheManger.Get(key); if (cacheContent != null) { return (T)cacheContent; } T value = base.Get<T>(index); CacheManger.Set(key, value, new CacheDependency(filePath)); return value; } } }
單元測試
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<IConfigProvider>(); _configContext = _kernel.Get<ConfigContext>(); } [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<RedisItemConfig> { new RedisItemConfig() { Text = "MasterChief" }, new RedisItemConfig() { Text = "Config." } }; _configContext.Save(redisConfig, "prod"); _configContext.Save(redisConfig, "alpha"); RedisConfig prodRedisConfig = _configContext.Get<RedisConfig>("prod"); Assert.IsNotNull(prodRedisConfig); prodRedisConfig = _configContext.Get<RedisConfig>("prod");//文件緩存測試 Assert.IsNotNull(prodRedisConfig); RedisConfig alphaRedisConfig = _configContext.Get<RedisConfig>("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<DaoConfig>("prod"); Assert.IsNotNull(prodDaoConfig); DaoConfig alphaDaoConfig = _configContext.Get<DaoConfig>("alpha"); Assert.IsNotNull(alphaDaoConfig); } } }
本地配置會在程序根目錄Config下,如圖:
配置文件基於XML持久化存儲,如圖:
a. 派生實現ValidateCodeType抽象類,來自定義驗證碼樣式;
b. 派生實現VerifyCodeHandler抽象類,快速切換須要顯示驗證碼;
代碼使用說明:
Mvc 簡單使用以下:
/// <summary> /// 處理生成Mvc 程序驗證碼 /// </summary> 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; } }
WebForm 簡單使用以下:
/// <summary> /// WebFormVerifyCodeHandler 的摘要說明 /// </summary> 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; } }
a. 目前支持Json以及Protobuf兩種方式的序列化與反序列化
b. 能夠經過實現接口ISerializer擴展實現其餘方式;
代碼使用說明:
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<Person>(jsonText); Console.WriteLine($"{serializer.GetType().Name}-Deserialize" + getPerson); #endregion #region 集合序列化與反序列化 var persons = new List<Person>(); 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<List<Person>>(jsonText); foreach (var item in getPersons) Console.WriteLine($"{serializer.GetType().Name}-Deserialize" + item); #endregion }
a. 基於Npoi實現,能夠基於接口IExcelManger擴展實現諸如MyXls等;
b. 目前實現了將Excel導出DataTable和DataTable導出到Excel文件;
c. 後續完善諸如整個Excel文件導入導出等;
代碼使用說明:
將DataTable導出到Excel文件
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; }
將Excel文件導出DataTable
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); }
a.支持下載文件加密;
b.支持下載自定義限速;
c.經過DownloadHandler抽象類實現擴展諸如在Asp.Net Mvc實現;
代碼使用說明:
文件下載配置文件
<?xml version="1.0" encoding="utf-16"?> <DownloadConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" FileNameEncryptorIv="0102030405060708090a0a0c0d010208" FileNameEncryptorKey="DotnetDownloadConfig" LimitDownloadSpeedKb="1024" DownLoadMainDirectory="D:\OneDrive\軟件\工具\"> </DownloadConfig>
在WebForm實現DownloadHandler抽象類,迅速實現文件下載
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); } }
修改Web.Config 文件
<system.web> <compilation debug="true" targetFramework="4.5"/> <httpRuntime targetFramework="4.5"/> <httpHandlers> <add verb="*" path="FileDownloadHandler.ashx" type="MasterChief.DotNet.Framework.WbSample.BackHandler.FileDownloadHandler" /> </httpHandlers> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true" /> </system.webServer>