All Projects → YanZhiwei → Masterchief

YanZhiwei / Masterchief

Licence: mit
C# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。

Programming Languages

csharp
926 projects

Projects that are alternatives of or similar to Masterchief

Oss.common
oss基础类库,主要涉及基础实体,加密算法,xml序列化,以及其他扩展方法等
Stars: ✭ 56 (-70.53%)
Mutual labels:  cache, log
Java Library Examples
💪 example of common used libraries and frameworks, programming required, don't fork man.
Stars: ✭ 204 (+7.37%)
Mutual labels:  kafka, cache
Entityframeworkcore.cacheable
EntityFrameworkCore second level cache
Stars: ✭ 138 (-27.37%)
Mutual labels:  entity-framework, cache
Androidutilcode
AndroidUtilCode 🔥 is a powerful & easy to use library for Android. This library encapsulates the functions that commonly used in Android development which have complete demo and unit test. By using it's encapsulated APIs, you can greatly improve the development efficiency. The program mainly consists of two modules which is utilcode, which is commonly used in development, and subutil which is rarely used in development, but the utils can be beneficial to simplify the main module. 🔥
Stars: ✭ 30,239 (+15815.26%)
Mutual labels:  cache, log
Drain3
Drain log template miner in Python3
Stars: ✭ 71 (-62.63%)
Mutual labels:  kafka, log
Illuminati
This is a Platform that collects all the data accuring in your Application and shows the data in real time by using Kibana or other tools.
Stars: ✭ 106 (-44.21%)
Mutual labels:  kafka, log
Thinkgo
A lightweight MVC framework written in Go (Golang).
Stars: ✭ 184 (-3.16%)
Mutual labels:  cache, log
Discordchatexporter
Exports Discord chat logs to a file
Stars: ✭ 3,198 (+1583.16%)
Mutual labels:  log
Reliable
mq transaction, tcc, eventually consistency. tx life cycle: all listeners handled, if necessary, produce next message
Stars: ✭ 187 (-1.58%)
Mutual labels:  kafka
Openmessaging Benchmark
OpenMessaging Benchmark Framework
Stars: ✭ 184 (-3.16%)
Mutual labels:  kafka
Http Cache
High performance Golang HTTP middleware for server-side application layer caching, ideal for REST APIs
Stars: ✭ 184 (-3.16%)
Mutual labels:  cache
Wechatvideocourse
《微信公众号+小程序快速开发》视频教程课件及代码
Stars: ✭ 185 (-2.63%)
Mutual labels:  cache
Elefant
Elefant, the refreshingly simple PHP CMS and web framework.
Stars: ✭ 188 (-1.05%)
Mutual labels:  cache
Mockedstreams
Scala DSL for Unit-Testing Processing Topologies in Kafka Streams
Stars: ✭ 184 (-3.16%)
Mutual labels:  kafka
Acho
The Hackable Log
Stars: ✭ 189 (-0.53%)
Mutual labels:  log
Cacule Cpu Scheduler
The CacULE CPU scheduler is based on interactivity score mechanism. The interactivity score is inspired by the ULE scheduler (FreeBSD scheduler).
Stars: ✭ 185 (-2.63%)
Mutual labels:  cache
Kafdrop
Kafka Web UI
Stars: ✭ 3,158 (+1562.11%)
Mutual labels:  kafka
Kafka Proxy
Proxy connections to Kafka cluster. Connect through SOCKS Proxy, HTTP Proxy or to cluster running in Kubernetes.
Stars: ✭ 186 (-2.11%)
Mutual labels:  kafka
Logger
✔️ Simple, pretty and powerful logger for android
Stars: ✭ 13,093 (+6791.05%)
Mutual labels:  log
Zbnetworking
AFNetworking4.X封装 GET/POST /PUT/PATCH /DELETE / Upload /DownLoad 网络请求 添加了请求缓存,断点下载,显示缓存大小,删除缓存,取消当前请求等功能
Stars: ✭ 186 (-2.11%)
Mutual labels:  cache

C# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。

项目架构思维导图:

设计

目录

1. 数据库访问


a. 支持Dapper和Entity Framework 两种ORM框架;

b. 通过IOC可以很少代码在Dapper和Entity Framework切换;

c. 实现Repository和UnitOfWork;

d. CURD以及事务实现简单,很大程度关注业务实现即可;

代码使用说明:

  1. Create 添加
public bool Create(EFSample samle)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.Create<EFSample>(samle);
    }
}
  1. Delete 删除
public bool Delete(EFSample sample)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.Delete(sample);
    }
}
  1. Update 修改
public bool Update(EFSample sample)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.Update(sample);
    }
}
  1. GetByKeyID 根据主键查询
public EFSample GetByKeyID(Guid id)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.GetByKeyID<EFSample>(id);
    }
}
  1. GetList 条件查询集合
public List<EFSample> GetList(Expression<Func<EFSample, bool>> predicate = null)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.GetList<EFSample>(predicate);
    }
}
  1. Exist 条件查询是否存在
public bool Exist(Expression<Func<EFSample, bool>> predicate = null)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.Exist<EFSample>(predicate);
    }
}
  1. SqlQuery 执行Sql脚本
public List<EFSample> SqlQuery(string sql, DbParameter[] parameter)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.SqlQuery<EFSample>(sql, parameter)?.ToList();
    }
}
  1. CreateWithTransaction 事务处理
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;
}
  1. GetFirstOrDefault 条件查询第一项或默认数据
public EFSample GetFirstOrDefault(Expression<Func<EFSample, bool>> predicate = null)
{
    using (IDbContext dbcontext = _contextFactory.Create())
    {
        return dbcontext.GetFirstOrDefault<EFSample>(predicate);
    }
}
  1. 单元测试以及Sql Server脚本
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>[email protected]
and [email protected]
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

2. 日志


a. 目前实现基于Log4Net的本地文件日志以及Kafka ELK的日志;

b. 基于接口ILogService可以很容易扩展其他日志显示;

代码使用说明

  1. 配置依赖注入,日志实现方式,这里采用文件日志形式
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();
        }
    }
}
  1. 拷贝日志config文件到项目内,并设置属性“始终复制”到输出目录,您可以根据项目需求调整config内容
<?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&quot;.log&quot;" />
      <!--是否固定文件名-->
      <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&quot;.log&quot;" />
      <!--是否固定文件名-->
      <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&quot;.log&quot;" />
      <!--是否固定文件名-->
      <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&quot;.log&quot;" />
      <!--是否固定文件名-->
      <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&quot;.log&quot;" />
      <!--是否固定文件名-->
      <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>
  1. 单元测试
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");
        }
    }
}

3. 缓存


a. 支持本地内存缓存,HttpRequest请求缓存,Redis缓存;

b. 基于ICacheProvider接口,可以很容易扩展其他缓存实现;

代码使用说明:

  1. 配置依赖注入,缓存实现方式,这里采用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();
            }
        }
    }
    
  2. 单元测试

    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);
            }
        }
    }
    
    

4. 配置


a. 目前支持配置文件本地持久化,并且支持配置文件缓存依赖减少读取文件次数;

b. 基于IConfigProvider接口,可以很容易扩展其他配置实现;

代码使用说明:

  1. 配置依赖注入,配置实现方式,这里采用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();
            }
        }
    }
    
  2. 扩展配置上下文基于文件依赖

    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;
            }
        }
    }
    
  3. 单元测试

    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);
            }
        }
    }
    
  4. 本地配置会在程序根目录Config下,如图:

    1552231625890

  5. 配置文件基于XML持久化存储,如图:

    1552231725395

5. 验证码


a. 派生实现ValidateCodeType抽象类,来自定义验证码样式;

b. 派生实现VerifyCodeHandler抽象类,快速切换需要显示验证码;

代码使用说明:

  1. 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;
        }
    }
    
  2. 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;
        }
    }
    
    

6. 序列化与反序列化


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
}

7. EXCEL导入导出


a. 基于Npoi实现,可以基于接口IExcelManger扩展实现诸如MyXls等;

b. 目前实现了将Excel导出DataTable和DataTable导出到Excel文件;

c. 后续完善诸如整个Excel文件导入导出等;

代码使用说明:

  1. 将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;
    }
    

  2. 将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);
    }
    

8. 文件下载


a.支持下载文件加密;

b.支持下载自定义限速;

c.通过DownloadHandler抽象类实现扩展诸如在Asp.Net Mvc实现;

代码使用说明:

  1. 文件下载配置文件

    <?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>
    
  2. 在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);
        }
    }
    
  3. 修改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>
    
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].