C# 嵌入dll

 

  在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形式总归让人不爽,那么有办法让生成的软件中直接就包含这个dll文件吗,这样就可以不用dll跟着exe走了,避免单独不能运行的情况。

答案是有的!

在工程项目目录下找到Resources.resx文件并点击,然后按下面操作,添加资源,将你要加入的dll添加进来。

操作完成后,就会在下面的内容框里看到你添加进来的dll。

然后在工程中加入下面这个函数代码:

  1. 1 System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  2. 2 {
  3. 3 string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
  4. 4 dllName = dllName.Replace(".", "_");
  5. 5 if (dllName.EndsWith("_resources")) return null;
  6. 6 System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
  7. 7 byte[] bytes = (byte[])rm.GetObject(dllName);
  8. 8 return System.Reflection.Assembly.Load(bytes);
  9. 9 }

在InitializeComponent();之前调用。这样生成的exe就包含这个dll文件啦。

  1. 1 public Form1()
  2. 2 {
  3. 3 this.StartPosition = FormStartPosition.CenterScreen;
  4. 4 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
  5. 5 InitializeComponent();
  6. 6 }

动软代码生成器基础使用

 

前几天做项目用到了动软代码生成器

对刚出社会的我来说可以说什么都不知道,对此赶紧学习了一下才发现这是李天平老师开发的软件膜拜一下!

以此总结一下

1.软件基本使用

我在百度下载的是V2.78版的

添加服务器 选择要连接的数据库

点击连接/测试 看是否成功,同时选择要连接的数据库,不然加载全部库要等好久的

学习使用呢,下载完成后有在左边模板管理有一个

2.所有对象使用

3.模板生成

这里直接打开生成会报错

需要点开模板代码生成,以下是相应的页面

然后再去点生成模板

可以对相应的字段修改,下面这个是自带的模板示例 可以照着这个去写自己业务逻辑

也可以点击批量模板生成

但有一个问题就是生成的文件名都是表名,如果表很多的话就要改很多,我们用生成器就是为了节约时间

为了解决这个问题我写了WindowsForms 可以批量修改生成文件的后缀名已达到项目的符合的命名规范

批量修改文件名下载地址:https://files.cnblogs.com/files/yuanzijian-ruiec/%E6%96%87%E4%BB%B6%E5%90%8D%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9.zip

参考原文:https://www.cnblogs.com/ltp/archive/2011/05/25/2057151.html

有时候总听到网友说网站运行好慢,不知如何是好;有时候也总见到一些朋友写的网站功能看起来非常好,但访问性能却极其的差。没有“勤俭节约”的意识,势必会造成“铺张浪费”。如何应对这种情况,充分利用系统缓存则是首要之道。

系统缓存有什么好处呢?举个简单的例子,你想通过网页查询某些数据,而这些数据并非实时变化,或者变化的时间是有期限的。例如查询一些历史数据。那么每个用户每次查的数据都是一样的。如果不设置缓存,ASP.NET也会根据每个用户的请求重复查询n次,这就增加了不必要的开销。所以,可能的情况下尽量使用缓存,从内存中返回数据的速度始终比去数据库查的速度快,因而可以大大提供应用程序的性能。毕竟现在内存非常便宜,用空间换取时间效率应该是非常划算的。尤其是对耗时比较长的、需要建立网络链接的数据库查询操作等。

缓存功能是大型网站设计一个很重要的部分。由数据库驱动的Web应用程序,如果需要改善其性能,最好的方法是使用缓存功能。

系统缓存全解析文章索引

15.4.1      缓存的分类

从分布上来看,我们可以概括为客户端缓存和服务器端缓存。如图15-1所示:

图15-1  缓存的分类

客户端缓存—— 这点大家都有直观的印象。比如你去一个新的网站,第一次可能要花一阵子时间才能载入整个页面。而以后再去呢,时间就会大大的缩短,原因就在于这个客户端缓存。现在的浏览器都比较智能,它会在客户机器的硬盘上保留许多静态的文件,比如各种gif,jpeg文件等等。等以后再去的时候,它会尽量使用本地缓存里面的文件。只有服务器端的文件更新了,或是缓存里面的文件过期了,它才会再次从服务器端下载这些东西。很多时候是IE替我们做了这件事情。

服务器端缓存—— 有些东西没法或是不宜在客户端缓存,那么我们只好在服务器端想想办法了。服务器端缓存从性质上看,又可以分为两种。

(1)静态文件缓存

好多页面是静态的,很少改动,那么这种文件最适于作静态缓存。现在的IIS 6.0这部分内容是直接存放在Kernel的内存中,由HTTP.SYS直接管理。由于它在Kernel Space,所以它的性能非常的高。用户的请求如果在缓存里面,那么HTTP.SYS直接将内容发送到network driver上去,不需要像以前那样从IIS的User space的内存copy到Kernel中,然后再发送到TCP/IP stack上。Kernel level cache几乎是现在高性能Web server的一个必不可少的特性。

(2)动态缓存

动态缓存是比较有难度的。因为你在缓存的时候要时刻注意一个问题,那就是缓存的内容是不是已经过时了。因为内容过时了可能会有很严重的后果。比如网上买卖股票的网站。你给别人提供的价格是过时的,那人家非砍了你不可。缓存如何发现自己是不是过时就是一个非常复杂的问题。

在ASP.NET中,常见的动态缓存主要有以下几种手段:

Ø  传统缓存方式

Ø  页面输出缓存。

Ø  页面局部缓存。

Ø  利用.NET提供的System.Web.Caching 缓存。

Ø  缓存依赖。

 

15.4.2  传统缓存方式

比如将可重复利用的东西放到Application或是Session中去保存。

 

 Session["Style"] = val;
 Application["Count"] = 0;

(选自《亮剑.NET:.NET深入体验与实战精要》第15章)

.NET开发中的事务处理大比拼

Posted on 2009-06-17 20:38 李天平 阅读(5199) 评论(2) 编辑 收藏

事务是一组组合成逻辑工作单元的数据库操作,在系统执行过程中可能会出错,但事务将控制和维护每个数据库的一致性和完整性。事务处理的主要特征是,任务要么全部完成,要么都不完成。在写入一些记录时,要么写入所有记录,要么什么都不写入。如果在写入一个记录时出现了一个失败,那么在事务处理中已写入的其他数据就会回滚。事务可能由很多单个任务构成。

简单事务的一个常见例子:把钱从A账户转到B账户,这涉及两项任务,即从A账户把钱取出来;把钱存入B账户。两项任务要么同时成功,要么一起失败,给予回滚,以便保持账户的状态和原来相同。否则,在执行某一个操作的时候可能会因为停电、网络中断等原因而出现故障,所以有可能更新了一个表中的行,但没有更新相关表中的行。如果数据库支持事务,则可以将数据库操作组成一个事务,以防止因这些事件而使数据库出现不一致。

事务的ACID属性如下。

l  原子性(Atomicity):事务的所有操作是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。原子性消除了系统处理操作子集的可能性。

l  一致性(Consistency):数据从一种正确状态转换到另一种正确状态。事务在完成时,必须使所有的数据都保持一致。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。当事务结束时,所有的内部数据结构都必须是正确的。在存款取款的例子中,逻辑规则是,钱是不能凭空产生或销毁的,对于每个(收支)条目必须有一个相应的抵衡条目产生,以保证账户是平的。

l  隔离性(Isolation):由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。查看数据时数据所处的状态,要么是事务修改它之前的状态,要么是事务修改它之后的状态。简单的理解就是,防止多个并发更新彼此干扰。事务在操作数据时与其他事务操作隔离。隔离性一般是通过加锁的机制来实现的。

l  持久性(Durability):事务完成之后,它对于系统的影响是永久性的。已提交的更改即使在发生故障时也依然存在。

对于事务的开发,.NET平台也为我们提供了几种非常简单方便的事务机制。无论是在功能上还是性能上都提供了优秀的企业级事务支持。

.NET开发者可以使用以下5种事务机制:

l  SQL和存储过程级别的事务。

l  ADO.NET级别的事务。

l  ASP.NET页面级别的事务。

l  企业级服务COM+事务。

l  System.Transactions 事务处理。

这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。下面就开始分别说明日常开发中5种事务的具体使用。

.NET开发中的事务处理大比拼 之 SQL和存储过程级别事务

.NET开发中的事务处理大比拼 之 ADO.NET级别的事务

.NET开发中的事务处理大比拼 之 ASP.NET页面级别的事务

.NET开发中的事务处理大比拼 之 企业级服务COM+事务

.NET开发中的事务处理大比拼 之 System.Transactions

选自《亮剑.NET. .NET深入体验与实战精要》 5.4 节。

c# partial 关键字的使用

说一个场景:EntityFramework可以自动创建数据库映射的实体类,该类不可修改(更新时会清空自定义部分),类似Winform下自动生成的.designer.cs文件。因此可以通过partial标记来编写自定义的扩展功能。

C#之数据类型学习

 

C#有以下几种数据类型:

数据类型案例以及取值范围:

界面:

选择int时:

选中long时:

选中float时:

选中double时:

选中decimal时:

选中string时:

选中char时:

选中Bool时:

源代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SecondWpf
{
     /// <summary>
     /// MainWindow.xaml 的交互逻辑
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
          
         }

private void Button_Click(object sender, RoutedEventArgs e)
         {
             Close();//当Quit键被按下以后,退出系统
         }

private void ListBoxItem_Selected(object sender, RoutedEventArgs e)
         {
             int variable,IntMax,IntMin;
             variable = 42;
             IntMax = (int)Math.Pow(2, 32)-1;
             IntMin = (int)Math.Pow(-2, 32);
             Value.Text = variable.ToString() ;
             Down.Text = IntMin.ToString();
             Uper.Text = IntMax.ToString();
         }

private void List1_Selected(object sender, RoutedEventArgs e)
         {
             long LongMax, LongMin,variable;
             variable = 42L;
      
             LongMax = (long)Math.Pow(2, 63) - 1;
             LongMin = (long)Math.Pow(-2, 63);
             Value.Text = variable.ToString();
             Down.Text = LongMax.ToString();
             Uper.Text = LongMin.ToString();
         }

private void List2_Selected(object sender, RoutedEventArgs e)
         {
             float variable;
             string FloatMax, FloatMin;
             variable = 0.42f;
             FloatMax = "(+-)1.5*10^45";
             FloatMin = "(+-)3.4 * 10 ^ 45";
             Value.Text = variable.ToString();
             Down.Text = FloatMax;
             Uper.Text = FloatMin;
         }

private void List3_Selected(object sender, RoutedEventArgs e)
         {
             double variable;
             string DoubleMax;
             string DoubleMin;
             variable = 0.43;
             DoubleMax = "+-5.0*10^-324";
             DoubleMin = "+-1.7*10^308";
             Value.Text = variable.ToString();
             Down.Text = DoubleMax;
             Uper.Text = DoubleMin;

}

private void List4_Selected(object sender, RoutedEventArgs e)
         {
             decimal coin;
             string DecimalMax, DecimalMin;
             coin = 0.42M;
             DecimalMax ="+-1.0*10^-28";
             DecimalMin = "+-7.9*10^28"; 
             Value.Text = coin.ToString();
             Down.Text = DecimalMax.ToString();
             Uper.Text = DecimalMin.ToString();
         }

private void List5_Selected(object sender, RoutedEventArgs e)
         {
             string vest;
             vest = "你好!";
             Value.Text = vest;
             Down.Text = "null";
             Uper.Text = "null";
         }

private void List6_Selected(object sender, RoutedEventArgs e)
         {
             char grill;
             int CharMax, CharMin;
             grill = 'x';
             CharMax = (int)Math.Pow(2, 16) - 1;
             CharMin = 0;
             Value.Text = grill.ToString();
             Down.Text = CharMin.ToString();
             Uper.Text = CharMax.ToString();
         }

private void List7_Selected(object sender, RoutedEventArgs e)
         {
             bool teeth;
             teeth = false;
             Value.Text = teeth.ToString();
             Down.Text ="Ture";
             Uper.Text = "Flase";
         }
     }
}

距离上一篇文章《基于EF Core的Code First模式的DotNetCore快速开发框架》已过去大半个年头,时光荏苒,岁月如梭。。。比较尴尬的是,在这大半个年头里,除了日常带娃溜娃做饭,偶尔接几个私单外,个人开源项目几乎没啥动静。那么日常工作干些什么呢?肯定是坚守Nfx啊。。。为什么呢?不做Nfx那是不可能的,毕竟要吃饭...讲真,大山城作为新进一线网红大城市环境,dotneter们活得非常坚挺的,眼看又一波猛涨的房价和这危机年,还是默默加完班后夜跑几十公里,锻炼好身体,多做几单深夜兼职,兴许运气来了能碰一个少奋斗20年的捷径...前提是得做好各种滴水不漏的安全措施以防止猝死暴毙...

至于多坑还是坑多,早已傻傻分不清,坊间谣传民间大神的【重庆求职防坑手册】早已被喷的不能自已,甚至已经下架

契机

前不久,科技巨头微软粑粑发布了dotnetcore 2.1,以其一贯的尿性作风,应该可以上车了。然而我还在坚守Nfx,毕竟公司成熟平台成熟产品以及成熟人力结构,冒然大跃进是肯定要承担各种被扣帽子风险的。虽然明面上上车无望,私下勾搭还是有戏。前些时日,接到道友们热情诚挚的需求,添加对DB First的支持,懒人有懒福...

更新内容

Gayhub地址:https://github.com/VictorTzeng/Zxw.Framework.NetCore
 
具体更新内容,大大小小还是有点多,这里就不啰嗦正经的话,具体情况具体代码里见。
  1. 添加EFCore直接返回DataTable功能
  2. DBFirst功能,目前仅支持SQL Server、MySQL、NpgSQL三种数据库。根据已存在的数据表直接生成实体代码,详见CodeGenerator
  3. 添加单元测试项目,并完成对以上两点新功能的测试
  4. 引入IOC容器Aspectcore.Injector,详见AspectCoreContainer.cs

手拿来,手把手摸你

目前仅支持Sqlserver、MySQL、NpgSQL等三种数据库,具体用法如下:

  1. 注入DbContextOption
    1. 1 services.Configure<DbContextOption>(options =>
    2. 2 {
    3. 3 options.ConnectionString =
    4. 4 "User ID=zengxw;Password=123456;Host=localhost;Port=5432;Database=ZxwPgDemo;Pooling=true;";
    5. 5 });
    6. 6 services.AddScoped<IDbContextCore, PostgreSQLDbContext>(); //注入EF上下文

    注入CodeGenerateOption

    1. 1 services.Configure<CodeGenerateOption>(options =>
    2. 2 {
    3. 3 options.OutputPath = "F:\\Test\\PostgreSQL";
    4. 4 options.ModelsNamespace = "Zxw.Framework.Website.Models";
    5. 5 options.IRepositoriesNamespace = "Zxw.Framework.Website.IRepositories";
    6. 6 options.RepositoriesNamespace = "Zxw.Framework.Website.Repositories";
    7. 7 options.ControllersNamespace = "Zxw.Framework.Website.Controllers";
    8. 8 });

    调用GenerateAllCodesFromDatabase生成所有代码

  1. 1 CodeGenerator.GenerateAllCodesFromDatabase(true);

总结与计划

工作之余,多陪家人多陪孩子,多读书多看报,多锻炼身体,毕竟钱是挣不完的。。。如果各位道友有多的可以全都扔过来,哈哈哈
 
 

基于EF Core的Code First模式的DotNetCore快速开发框架

 

前言

最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单。所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code first模式,从而可以进行快速开发。几个单子做完下来,顺便总结整理一下,近些时候也一直在学习dotnetcore,索性将项目都升级了,于是便有了这一套“基于EF Core的Code First模式的DotNetCore快速开发框架”。至于code first模式的优劣,此文将不再赘述。至于本文的目的,一是为了总结和整理工作这几年所学的一些知识,方便以后能够快速高效地接入项目中。再是分享出来,跟大家一起探讨学习,一起进步。欢迎各路大佬指正和建议^_^

项目地址

GitHub:

dotnetcore版本:https://github.com/VictorTzeng/Zxw.Framework.NetCore

.net framework版本:https://github.com/VictorTzeng/Zxw.Framework.Nfx

码云:

dotnetcore版本:https://gitee.com/ceo_bitch/Zxw.Framework.NetCore

.net framework版本:https://gitee.com/ceo_bitch/Zxw.Framework.Nfx

项目架构

此项目主要分成两部分:Zxw.Framework.NetCore (核心类库)和 NetCore.Sample (示例)两部分。如图所示:

Zxw.Framework.NetCore 项目说明:

  • Attributes —— 一些常用的属性
  • CodeGenerator —— 代码生成器,用于生成Repository和Service层的代码
  • CodeTemplate —— Repository和Service层代码模板
  • EfDbContext —— EF上下文
  • Extensions —— 一些常用的扩展方法
  • Filters —— 一些常用的拦截器
  • Helpers —— 一些常用的帮助类
  • IoC —— IoC容器封装类,Autofac
  • IRepositories —— Repository接口类
  • IServices —— Service接口类
  • Middlewares —— 中间件
  • Models —— 实体接口类,IBaseModel<TKey>
  • Options —— 一些常用的配置类
  • Repositories —— Repository层的父类
  • Services —— Service层的父类

框架使用

如 NetCore.Sample 所示,按照此项目结构创建好:

  • Zxw.Framework.Website —— 网站
  • Zxw.Framework.Website.Controllers —— 控制器
  • Zxw.Framework.Website.IRepositories —— 仓储接口
  • Zxw.Framework.Website.IServices —— Service接口
  • Zxw.Framework.Website.Models —— 实体
  • Zxw.Framework.Website.Repositories —— 仓储
  • Zxw.Framework.Website.Services —— Services
  • Zxw.Framework.Website.ViewModels —— ViewModels

安装nuget package:

Install-Package Zxw.Framework.NetCore -Version 1.0.1

需要注意以下几点:

  1. 所有实体都需实现IBaseModel<TKey>接口(TKey是主键类型),如果需要在数据库中生成对应的数据表
  2. 如果IRepositories、IServices、Repositories、Services这四个项目没有单独建立,调用代码生成器生成的代码将存在于调用项目的目录下
  3. 利用代码生成器生成的代码文件需要手动添加到项目中

实体示例:

  1. 1 using System.ComponentModel.DataAnnotations;
  2. 2 using System.ComponentModel.DataAnnotations.Schema;
  3. 3 using Zxw.Framework.NetCore.Models;
  4. 4
  5. 5 namespace Zxw.Framework.Website.Models
  6. 6 {
  7. 7 public class TutorClassType:IBaseModel<int>
  8. 8 {
  9. 9 [Key]
  10. 10 [Column("TutorClassTypeId")]
  11. 11 public int Id { get; set; }
  12. 12
  13. 13 [Required]
  14. 14 [StringLength(maximumLength:50)]
  15. 15 public string TutorClassTypeName { get; set; }
  16. 16 public bool Active { get; set; } = true;
  17. 17 [StringLength(maximumLength:200)]
  18. 18 public string Remark { get; set; }
  19. 19 public int TutorClassCount { get; set; }
  20. 20 }
  21. 21 }

在Startup.cs文件中使用:

  1. 1 using System;
  2. 2 using System.Text;
  3. 3 using log4net;
  4. 4 using log4net.Repository;
  5. 5 using Microsoft.AspNetCore.Builder;
  6. 6 using Microsoft.AspNetCore.Hosting;
  7. 7 using Microsoft.Extensions.Caching.Distributed;
  8. 8 using Microsoft.Extensions.Caching.Memory;
  9. 9 using Microsoft.Extensions.Configuration;
  10. 10 using Microsoft.Extensions.DependencyInjection;
  11. 11 using Zxw.Framework.NetCore.EfDbContext;
  12. 12 using Zxw.Framework.NetCore.Filters;
  13. 13 using Zxw.Framework.NetCore.Helpers;
  14. 14 using Zxw.Framework.NetCore.IoC;
  15. 15 using Zxw.Framework.NetCore.Options;
  16. 16
  17. 17 namespace Zxw.Framework.Website
  18. 18 {
  19. 19 public class Startup
  20. 20 {
  21. 21 public static ILoggerRepository repository { get; set; }
  22. 22 public Startup(IConfiguration configuration)
  23. 23 {
  24. 24 Configuration = configuration;
  25. 25 //初始化log4net
  26. 26 repository = LogManager.CreateRepository("NETCoreRepository");
  27. 27 Log4NetHelper.SetConfig(repository, "log4net.config");
  28. 28 }
  29. 29
  30. 30 public IConfiguration Configuration { get; }
  31. 31
  32. 32 // This method gets called by the runtime. Use this method to add services to the container.
  33. 33 public IServiceProvider ConfigureServices(IServiceCollection services)
  34. 34 {
  35. 35 services.AddMvc(option=>
  36. 36 {
  37. 37 option.Filters.Add(new GlobalExceptionFilter());
  38. 38 });
  39. 39 services.AddMemoryCache();//启用MemoryCache
  40. 40 services.AddDistributedRedisCache(option =>
  41. 41 {
  42. 42 option.Configuration = "localhost";//redis连接字符串
  43. 43 option.InstanceName = "";//Redis实例名称
  44. 44 });//启用Redis
  45. 45 services.Configure<MemoryCacheEntryOptions>(
  46. 46 options => options.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)) //设置MemoryCache缓存有效时间为5分钟。
  47. 47 .Configure<DistributedCacheEntryOptions>(option =>
  48. 48 option.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5));//设置Redis缓存有效时间为5分钟。
  49. 49 return InitIoC(services);
  50. 50 }
  51. 51
  52. 52 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  53. 53 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  54. 54 {
  55. 55 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  56. 56 if (env.IsDevelopment())
  57. 57 {
  58. 58 app.UseDeveloperExceptionPage();
  59. 59 app.UseBrowserLink();
  60. 60 }
  61. 61 else
  62. 62 {
  63. 63 app.UseExceptionHandler("/Home/Error");
  64. 64 }
  65. 65
  66. 66 app.UseStaticFiles();
  67. 67
  68. 68 app.UseMvc(routes =>
  69. 69 {
  70. 70 routes.MapRoute(
  71. 71 name: "default",
  72. 72 template: "{controller=Home}/{action=Index}/{id?}");
  73. 73 });
  74. 74 }
  75. 75 /// <summary>
  76. 76 /// IoC初始化
  77. 77 /// </summary>
  78. 78 /// <param name="services"></param>
  79. 79 /// <returns></returns>
  80. 80 private IServiceProvider InitIoC(IServiceCollection services)
  81. 81 {
  82. 82 var connectionString = Configuration.GetConnectionString("MsSqlServer");
  83. 83 var dbContextOption = new DbContextOption
  84. 84 {
  85. 85 ConnectionString = connectionString,
  86. 86 ModelAssemblyName = "Zxw.Framework.Website.Models",
  87. 87 DbType = DbType.MSSQLSERVER
  88. 88 };
  89. 89 var codeGenerateOption = new CodeGenerateOption
  90. 90 {
  91. 91 ModelsNamespace = "Zxw.Framework.Website.Models",
  92. 92 IRepositoriesNamespace = "Zxw.Framework.Website.IRepositories",
  93. 93 RepositoriesNamespace = "Zxw.Framework.Website.Repositories",
  94. 94 IServicsNamespace = "Zxw.Framework.Website.IServices",
  95. 95 ServicesNamespace = "Zxw.Framework.Website.Services"
  96. 96 };
  97. 97 IoCContainer.Register(Configuration);//注册配置
  98. 98 IoCContainer.Register(dbContextOption);//注册数据库配置信息
  99. 99 IoCContainer.Register(codeGenerateOption);//注册代码生成器相关配置信息
  100. 100 IoCContainer.Register(typeof(DefaultDbContext));//注册EF上下文
  101. 101 IoCContainer.Register("Zxw.Framework.Website.Repositories", "Zxw.Framework.Website.IRepositories");//注册仓储
  102. 102 IoCContainer.Register("Zxw.Framework.Website.Services", "Zxw.Framework.Website.IServices");//注册service
  103. 103 return IoCContainer.Build(services);
  104. 104 }
  105. 105 }
  106. 106 }

使用代码生成器:

  1. 1 using System;
  2. 2 using System.Diagnostics;
  3. 3 using Microsoft.AspNetCore.Mvc;
  4. 4 using Zxw.Framework.NetCore.CodeGenerator;
  5. 5 using Zxw.Framework.NetCore.Helpers;
  6. 6 using Zxw.Framework.Website.IServices;
  7. 7 using Zxw.Framework.Website.ViewModels;
  8. 8 using Zxw.Framework.Website.Models;
  9. 9
  10. 10 namespace Zxw.Framework.Website.Controllers
  11. 11 {
  12. 12 public class HomeController : Controller
  13. 13 {
  14. 14 private ITutorClassTypeService iTutorClassTypeService;
  15. 15
  16. 16 public HomeController(ITutorClassTypeService tutorClassTypeService)
  17. 17 {
  18. 18 if(tutorClassTypeService==null)
  19. 19 throw new ArgumentNullException(nameof(tutorClassTypeService));
  20. 20 iTutorClassTypeService = tutorClassTypeService;
  21. 21 }
  22. 22 public IActionResult Index()
  23. 23 {
  24. 24 CodeGenerator.Generate();//生成所有实体类对应的Repository和Service层代码文件
  25. 25 CodeGenerator.GenerateSingle<TutorClassType, int>();//生成单个实体类对应的Repository和Service层代码文件
  26. 26
  27. 27 return View();
  28. 28 }
  29. 29
  30. 30 public IActionResult About()
  31. 31 {
  32. 32 ViewData["Message"] = "Your application description page.";
  33. 33
  34. 34 return View();
  35. 35 }
  36. 36
  37. 37 public IActionResult Contact()
  38. 38 {
  39. 39 ViewData["Message"] = "Your contact page.";
  40. 40
  41. 41 return View();
  42. 42 }
  43. 43
  44. 44 public IActionResult Error()
  45. 45 {
  46. 46 return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
  47. 47 }
  48. 48
  49. 49 protected override void Dispose(bool disposing)
  50. 50 {
  51. 51 if (disposing)
  52. 52 {
  53. 53 iTutorClassTypeService.Dispose();
  54. 54 }
  55. 55 base.Dispose(disposing);
  56. 56 }
  57. 57 }
  58. 58 }

总结

写博客真的很费力,希望自己能够坚持下去。

最后,欢迎各路大佬建议和拍砖~~

【懒人有道】在asp.net core中实现程序集注入

 

前言

在asp.net core中,我巨硬引入了DI容器,我们可以在不使用第三方插件的情况下轻松实现依赖注入。如下代码:

  1. 1 // This method gets called by the runtime. Use this method to add services to the container.
  2. 2 public void ConfigureServices(IServiceCollection services)
  3. 3 {
  4. 4 //services.RegisterAssembly("IServices");
  5. 5 services.AddSingleton<IUserService, UserService>();
  6. 6 // Add framework services.
  7. 7 services.AddMvc();
  8. 8 services.AddMvcCore()
  9. 9 .AddApiExplorer();
  10. 10 services.AddSwaggerGen(options =>
  11. 11 {
  12. 12 options.SwaggerDoc("v1", new Info()
  13. 13 {
  14. 14 Title = "Swagger测试",
  15. 15 Version = "v1",
  16. 16 Description = "Swagger测试RESTful API ",
  17. 17 TermsOfService = "None",
  18. 18 Contact = new Contact
  19. 19 {
  20. 20 Name = "来来吹牛逼",
  21. 21 Email = "xxoo123@outlook.com"
  22. 22 },
  23. 23 });
  24. 24 //设置xml注释文档,注意名称一定要与项目名称相同
  25. 25 var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "WebApi.xml");
  26. 26 options.IncludeXmlComments(filePath);
  27. 27 });
  28. 28 }

但是,随着公司业务的扩大,系统项目的功能模块急剧扩张,新增了不下百个或者千个Repository和Service(有点夸张了...),这时候如此单纯滴注入就有点操蛋了。

打懒主意

我可不可以通过反射技术来实现对程序集的注入呢??

试试就试试

首先,我私自先制定一些类名的约束。规则嘛,反正是自己定。比如:

  • UserService --> IUserService
  • UserRepository --> IUserRepository
  • ......
  • ClassName --> IClassName

好了,我们下面开始编码:

  1. 1 /// <summary>
  2. 2 /// IServiceCollection扩展
  3. 3 /// </summary>
  4. 4 public static class ServiceExtension
  5. 5 {
  6. 6 /// <summary>
  7. 7 /// 用DI批量注入接口程序集中对应的实现类。
  8. 8 /// <para>
  9. 9 /// 需要注意的是,这里有如下约定:
  10. 10 /// IUserService --> UserService, IUserRepository --> UserRepository.
  11. 11 /// </para>
  12. 12 /// </summary>
  13. 13 /// <param name="service"></param>
  14. 14 /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
  15. 15 /// <returns></returns>
  16. 16 public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName)
  17. 17 {
  18. 18 if (service == null)
  19. 19 throw new ArgumentNullException(nameof(service));
  20. 20 if (string.IsNullOrEmpty(interfaceAssemblyName))
  21. 21 throw new ArgumentNullException(nameof(interfaceAssemblyName));
  22. 22
  23. 23 var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
  24. 24 if (assembly == null)
  25. 25 {
  26. 26 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");
  27. 27 }
  28. 28
  29. 29 //过滤掉非接口及泛型接口
  30. 30 var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);
  31. 31
  32. 32 foreach (var type in types)
  33. 33 {
  34. 34 var implementTypeName = type.Name.Substring(1);
  35. 35 var implementType = RuntimeHelper.GetImplementType(implementTypeName, type);
  36. 36 if (implementType != null)
  37. 37 service.AddSingleton(type, implementType);
  38. 38 }
  39. 39 return service;
  40. 40 }
  41. 41
  42. 42 /// <summary>
  43. 43 /// 用DI批量注入接口程序集中对应的实现类。
  44. 44 /// </summary>
  45. 45 /// <param name="service"></param>
  46. 46 /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
  47. 47 /// <param name="implementAssemblyName">实现程序集的名称(不包含文件扩展名)</param>
  48. 48 /// <returns></returns>
  49. 49 public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName)
  50. 50 {
  51. 51 if (service == null)
  52. 52 throw new ArgumentNullException(nameof(service));
  53. 53 if(string.IsNullOrEmpty(interfaceAssemblyName))
  54. 54 throw new ArgumentNullException(nameof(interfaceAssemblyName));
  55. 55 if (string.IsNullOrEmpty(implementAssemblyName))
  56. 56 throw new ArgumentNullException(nameof(implementAssemblyName));
  57. 57
  58. 58 var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
  59. 59 if (interfaceAssembly == null)
  60. 60 {
  61. 61 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");
  62. 62 }
  63. 63
  64. 64 var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName);
  65. 65 if (implementAssembly == null)
  66. 66 {
  67. 67 throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found");
  68. 68 }
  69. 69
  70. 70 //过滤掉非接口及泛型接口
  71. 71 var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);
  72. 72
  73. 73 foreach (var type in types)
  74. 74 {
  75. 75 //过滤掉抽象类、泛型类以及非class
  76. 76 var implementType = implementAssembly.DefinedTypes
  77. 77 .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType &&
  78. 78 t.GetInterfaces().Any(b => b.Name == type.Name));
  79. 79 if (implementType != null)
  80. 80 {
  81. 81 service.AddSingleton(type, implementType.AsType());
  82. 82 }
  83. 83 }
  84. 84
  85. 85 return service;
  86. 86 }
  87. 87 }

附上RuntimeHelper.cs的代码:

  1. 1 public class RuntimeHelper
  2. 2 {
  3. 3 /// <summary>
  4. 4 /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
  5. 5 /// </summary>
  6. 6 /// <returns></returns>
  7. 7 public static IList<Assembly> GetAllAssemblies()
  8. 8 {
  9. 9 var list = new List<Assembly>();
  10. 10 var deps = DependencyContext.Default;
  11. 11 var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包
  12. 12 foreach (var lib in libs)
  13. 13 {
  14. 14 try
  15. 15 {
  16. 16 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
  17. 17 list.Add(assembly);
  18. 18 }
  19. 19 catch (Exception)
  20. 20 {
  21. 21 // ignored
  22. 22 }
  23. 23 }
  24. 24 return list;
  25. 25 }
  26. 26
  27. 27 public static Assembly GetAssembly(string assemblyName)
  28. 28 {
  29. 29 return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
  30. 30 }
  31. 31
  32. 32 public static IList<Type> GetAllTypes()
  33. 33 {
  34. 34 var list = new List<Type>();
  35. 35 foreach (var assembly in GetAllAssemblies())
  36. 36 {
  37. 37 var typeInfos = assembly.DefinedTypes;
  38. 38 foreach (var typeInfo in typeInfos)
  39. 39 {
  40. 40 list.Add(typeInfo.AsType());
  41. 41 }
  42. 42 }
  43. 43 return list;
  44. 44 }
  45. 45
  46. 46 public static IList<Type> GetTypesByAssembly(string assemblyName)
  47. 47 {
  48. 48 var list = new List<Type>();
  49. 49 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
  50. 50 var typeInfos = assembly.DefinedTypes;
  51. 51 foreach (var typeInfo in typeInfos)
  52. 52 {
  53. 53 list.Add(typeInfo.AsType());
  54. 54 }
  55. 55 return list;
  56. 56 }
  57. 57
  58. 58 public static Type GetImplementType(string typeName, Type baseInterfaceType)
  59. 59 {
  60. 60 return GetAllTypes().FirstOrDefault(t =>
  61. 61 {
  62. 62 if (t.Name == typeName &&
  63. 63 t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
  64. 64 {
  65. 65 var typeInfo = t.GetTypeInfo();
  66. 66 return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
  67. 67 }
  68. 68 return false;
  69. 69 });
  70. 70 }
  71. 71 }

好了,到此就基本完成了,记得在Startup.cs加上:

  1. 1 // This method gets called by the runtime. Use this method to add services to the container.
  2. 2 public IServiceProvider ConfigureServices(IServiceCollection services)
  3. 3 {
  4. 4 services.RegisterAssembly("IServices");
  5. 5
  6. 6 // Add framework services.
  7. 7 services.AddMvc();
  8. 8 }

C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入的更多相关文章

  1. 手把手教你使用FineUI+动软代码生成器开发一个b/s结构的取送货管理信息系统(附源码)之开篇

    一 本系列随笔概览及产生的背景 近阶段接到一些b/s类型的软件项目,但是团队成员之前大部分没有这方面的开发经验,于是自己选择了一套目前网上比较容易上手的开发框架(FineUI),计划录制一套视频讲座, ...

  2. asp.net+mvc+easyui+sqlite 简单用户系统学习之旅(三)—— 简单登录页面+sqlite+动软代码生成器的使用

    上一节讲到利用easyui的layout.tree.tab和datagrid创建用户管理的页面,注意利用到easyui的页面一定要按顺序添加jQuery和easyUI的.js和.css样式,灵活查看e ...

  3. 解决“动软代码生成器在SqlServer中会将唯一索引识别为主键"的Bug

    动软代码生成器在SqlServer中,生成的代码会将唯一索引错误地识别为主键, 反编译源代码后,发现其中的SQL条件有误,现修复此Bug. 修复方法:将附件中的”Maticsoft.DbObjects ...

  4. 动软代码生成器三层用于winform

    DBUtility项目中的DbHelperSQL.cs (找自己对应的数据库类型) 修改前20行中的数据库连接字符串获取方式为: //数据库连接字符串(web.config来配置),多数据库可使用Db ...

  5. 动软代码生成器 可用于生成Entity层,可更改模板 /codesmith 也可以

    动软代码生成器官方下载地址:http://www.maticsoft.com/download.aspx 教程:http://jingyan.baidu.com/article/219f4bf7dfd ...

  6. 动软代码生成器连接Oracle 11g

      首先要说明的是:如果你连接的是远程的Oracle服务器,你本地机器必须装Oracle客户端,然后 用sqldeveloper 先建立一个连接. 然后你才能用.NET动软代码生成器连接到数据库. 因 ...

  7. 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持

    前言 距离上一篇文章<基于EF Core的Code First模式的DotNetCore快速开发框架>已过去大半个年头,时光荏苒,岁月如梭...比较尴尬的是,在这大半个年头里,除了日常带娃 ...

  8. 利用动软代码生成器 自动生成LINQ需要用的数据实体类 (转)

    首先先建立一个模板 名称随意 我起的“生成数据实体.cmt” 代码如下: <#@ template language="c#" HostSpecific="True ...

  9. 动软代码生成器,主子表增加的时候子表的parentID无法插入问题解决方案

    StringBuilder strSql=new StringBuilder(); strSql.Append("insert into HT_XunJiaMain("); str ...

随机推荐

  1. linux系统初始化——启动脚本是如何工作的

    启动脚本是如何工作的 Linux 使用的是基于 运行级(run-levels) 概念的称为 SysVinit 的专用启动工具.它在不同的系统上可能是完全不一样的,所以不能认为一个脚本在某个 Linux ...

  2. Fabric和Sawtooth技术分析(上)

    https://mp.weixin.qq.com/s?__biz=MjM5MDAxMTE0MA==&mid=2652049866&idx=1&sn=5b4aea961f3d64 ...

  3. layer相关

    关闭窗口 var index = parent.layer.getFrameIndex(window.name);parent.layer.close(index);

  4. java课后作业-5

    作业一:请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?“ 程序源代码; public class Lei { /** * @param args */ public static vo ...

  5. [AGC016B] Colorful Hats (结论)

    Description 有n个人,每个人都戴着一顶帽子.当然,帽子有不同的颜色. 现在,每个人都告诉你,他看到的所有其他人的帽子共有多少种颜色,请问你有没有符合所有人的描述的情况. Input 第一行 ...

  6. POJ1595 Prime Cuts

    Prime Cuts Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11961   Accepted: 4553 Descr ...

  7. C#中的继承与覆盖

    原文发布时间为:2009-03-03 -- 来源于本人的百度文章 [由搬家工具导入] //using System;//using System.Collections.Generic;using S ...

  8. css3 ani-2-trans, any to transform!!! css3 animation jingsui! Hover

    http://www.daqianduan.com/example?pid=2959 animation, transition, transform or ani 2 trans

  9. 多个电脑之间使用相同的ssh密钥

    首先我们给最先创建的密钥的电脑取名为OLD, 给后创建的密钥的电脑取名为NEW,在OLD上创建密钥,文件默认保存在 ~/.ssh/ 中: ssh-keygen –t rsa –C "your ...

  10. LeetCode OJ--Word Search **

    https://oj.leetcode.com/problems/word-search/ 类似于在棋盘上走步,走过的地方不能再走,每次都可以走当前位置的上.下.左.右,问能不能走出要求的形状来. 深 ...