安徽瑞银贵金属,我的海贼王,2010世界杯冠军是谁
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>
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Net Core Web Api项目与在NginX下发布的方法
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
IdentityServer4实现.Net Core API接口权限认证(快速入门)
ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现
网友评论