当前位置: 移动技术网 > IT编程>开发语言>.net > [开源]MasterChief 快速开发辅助类库

[开源]MasterChief 快速开发辅助类库

2019年04月25日  | 移动技术网IT编程  | 我要评论

安徽瑞银贵金属,我的海贼王,2010世界杯冠军是谁

c# 开发辅助类库,和士官长一样身经百战且越战越勇的战争机器,能力无人能出其右。
github:masterchief 欢迎star,欢迎issues;
项目架构思维导图:

设计

目录

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>=@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

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>

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网