标签:object login generic 入职 put eric pap vat framework
C# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。
GitHub:MasterChief 欢迎Star,欢迎Issues;
项目架构思维导图:
a. 支持Dapper和Entity Framework 两种ORM框架;
b. 通过IOC可以很少代码在Dapper和Entity Framework切换;
c. 实现Repository和UnitOfWork;
d. CURD以及事务实现简单,很大程度关注业务实现即可;
代码使用说明:
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的日志;
b. 基于接口ILogService可以很容易扩展其他日志显示;
代码使用说明
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>
标签:object login generic 入职 put eric pap vat framework
原文地址:https://www.cnblogs.com/MeetYan/p/10765721.html