在不少時候咱們在生成C#exe文件時,若是在工程裏調用了dll文件時,那麼若是不加以處理的話在生成的exe文件運行時須要連同這個dll一塊兒轉移,相比於一個單獨乾淨的exe,這種形式總歸讓人不爽,那麼有辦法讓生成的軟件中直接就包含這個dll文件嗎,這樣就能夠不用dll跟着exe走了,避免單獨不能運行的狀況。html
答案是有的!git
在工程項目目錄下找到Resources.resx文件並點擊,而後按下面操做,添加資源,將你要加入的dll添加進來。github
操做完成後,就會在下面的內容框裏看到你添加進來的dll。redis
而後在工程中加入下面這個函數代碼:數據庫
1 System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 2 { 3 string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", ""); 4 dllName = dllName.Replace(".", "_"); 5 if (dllName.EndsWith("_resources")) return null; 6 System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly()); 7 byte[] bytes = (byte[])rm.GetObject(dllName); 8 return System.Reflection.Assembly.Load(bytes); 9 }
在InitializeComponent();以前調用。這樣生成的exe就包含這個dll文件啦。c#
1 public Form1() 2 { 3 this.StartPosition = FormStartPosition.CenterScreen; 4 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 5 InitializeComponent(); 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章)
事務是一組組合成邏輯工做單元的數據庫操做,在系統執行過程當中可能會出錯,但事務將控制和維護每一個數據庫的一致性和完整性。事務處理的主要特徵是,任務要麼所有完成,要麼都不完成。在寫入一些記錄時,要麼寫入全部記錄,要麼什麼都不寫入。若是在寫入一個記錄時出現了一個失敗,那麼在事務處理中已寫入的其餘數據就會回滾。事務可能由不少單個任務構成。
簡單事務的一個常見例子:把錢從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種事務的具體使用。
1 .NET開發中的事務處理大比拼 之 SQL和存儲過程級別事務
2 .NET開發中的事務處理大比拼 之 ADO.NET級別的事務
3 .NET開發中的事務處理大比拼 之 ASP.NET頁面級別的事務
4 .NET開發中的事務處理大比拼 之 企業級服務COM+事務
5 .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年的捷徑...前提是得作好各類滴水不漏的安全措施以防止猝死暴斃...
契機
更新內容
- 添加EFCore直接返回DataTable功能
- DBFirst功能,目前僅支持SQL Server、MySQL、NpgSQL三種數據庫。根據已存在的數據表直接生成實體代碼,詳見CodeGenerator
- 添加單元測試項目,並完成對以上兩點新功能的測試
- 引入IOC容器Aspectcore.Injector,詳見AspectCoreContainer.cs
手拿來,手把手摸你
目前僅支持Sqlserver、MySQL、NpgSQL等三種數據庫,具體用法以下:
- 注入DbContextOption
-
1 services.Configure<DbContextOption>(options => 2 { 3 options.ConnectionString = 4 "User ID=zengxw;Password=123456;Host=localhost;Port=5432;Database=ZxwPgDemo;Pooling=true;"; 5 }); 6 services.AddScoped<IDbContextCore, PostgreSQLDbContext>(); //注入EF上下文
注入CodeGenerateOption
-
1 services.Configure<CodeGenerateOption>(options => 2 { 3 options.OutputPath = "F:\\Test\\PostgreSQL"; 4 options.ModelsNamespace = "Zxw.Framework.Website.Models"; 5 options.IRepositoriesNamespace = "Zxw.Framework.Website.IRepositories"; 6 options.RepositoriesNamespace = "Zxw.Framework.Website.Repositories"; 7 options.ControllersNamespace = "Zxw.Framework.Website.Controllers"; 8 });
調用GenerateAllCodesFromDatabase生成全部代碼
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
須要注意如下幾點:
- 全部實體都需實現IBaseModel<TKey>接口(TKey是主鍵類型),若是須要在數據庫中生成對應的數據表
- 若是IRepositories、IServices、Repositories、Services這四個項目沒有單獨創建,調用代碼生成器生成的代碼將存在於調用項目的目錄下
- 利用代碼生成器生成的代碼文件須要手動添加到項目中
實體示例:
1 using System.ComponentModel.DataAnnotations; 2 using System.ComponentModel.DataAnnotations.Schema; 3 using Zxw.Framework.NetCore.Models; 4 5 namespace Zxw.Framework.Website.Models 6 { 7 public class TutorClassType:IBaseModel<int> 8 { 9 [Key] 10 [Column("TutorClassTypeId")] 11 public int Id { get; set; } 12 13 [Required] 14 [StringLength(maximumLength:50)] 15 public string TutorClassTypeName { get; set; } 16 public bool Active { get; set; } = true; 17 [StringLength(maximumLength:200)] 18 public string Remark { get; set; } 19 public int TutorClassCount { get; set; } 20 } 21 }
在Startup.cs文件中使用:
1 using System; 2 using System.Text; 3 using log4net; 4 using log4net.Repository; 5 using Microsoft.AspNetCore.Builder; 6 using Microsoft.AspNetCore.Hosting; 7 using Microsoft.Extensions.Caching.Distributed; 8 using Microsoft.Extensions.Caching.Memory; 9 using Microsoft.Extensions.Configuration; 10 using Microsoft.Extensions.DependencyInjection; 11 using Zxw.Framework.NetCore.EfDbContext; 12 using Zxw.Framework.NetCore.Filters; 13 using Zxw.Framework.NetCore.Helpers; 14 using Zxw.Framework.NetCore.IoC; 15 using Zxw.Framework.NetCore.Options; 16 17 namespace Zxw.Framework.Website 18 { 19 public class Startup 20 { 21 public static ILoggerRepository repository { get; set; } 22 public Startup(IConfiguration configuration) 23 { 24 Configuration = configuration; 25 //初始化log4net 26 repository = LogManager.CreateRepository("NETCoreRepository"); 27 Log4NetHelper.SetConfig(repository, "log4net.config"); 28 } 29 30 public IConfiguration Configuration { get; } 31 32 // This method gets called by the runtime. Use this method to add services to the container. 33 public IServiceProvider ConfigureServices(IServiceCollection services) 34 { 35 services.AddMvc(option=> 36 { 37 option.Filters.Add(new GlobalExceptionFilter()); 38 }); 39 services.AddMemoryCache();//啓用MemoryCache 40 services.AddDistributedRedisCache(option => 41 { 42 option.Configuration = "localhost";//redis鏈接字符串 43 option.InstanceName = "";//Redis實例名稱 44 });//啓用Redis 45 services.Configure<MemoryCacheEntryOptions>( 46 options => options.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)) //設置MemoryCache緩存有效時間爲5分鐘。 47 .Configure<DistributedCacheEntryOptions>(option => 48 option.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5));//設置Redis緩存有效時間爲5分鐘。 49 return InitIoC(services); 50 } 51 52 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 53 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 54 { 55 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 56 if (env.IsDevelopment()) 57 { 58 app.UseDeveloperExceptionPage(); 59 app.UseBrowserLink(); 60 } 61 else 62 { 63 app.UseExceptionHandler("/Home/Error"); 64 } 65 66 app.UseStaticFiles(); 67 68 app.UseMvc(routes => 69 { 70 routes.MapRoute( 71 name: "default", 72 template: "{controller=Home}/{action=Index}/{id?}"); 73 }); 74 } 75 /// <summary> 76 /// IoC初始化 77 /// </summary> 78 /// <param name="services"></param> 79 /// <returns></returns> 80 private IServiceProvider InitIoC(IServiceCollection services) 81 { 82 var connectionString = Configuration.GetConnectionString("MsSqlServer"); 83 var dbContextOption = new DbContextOption 84 { 85 ConnectionString = connectionString, 86 ModelAssemblyName = "Zxw.Framework.Website.Models", 87 DbType = DbType.MSSQLSERVER 88 }; 89 var codeGenerateOption = new CodeGenerateOption 90 { 91 ModelsNamespace = "Zxw.Framework.Website.Models", 92 IRepositoriesNamespace = "Zxw.Framework.Website.IRepositories", 93 RepositoriesNamespace = "Zxw.Framework.Website.Repositories", 94 IServicsNamespace = "Zxw.Framework.Website.IServices", 95 ServicesNamespace = "Zxw.Framework.Website.Services" 96 }; 97 IoCContainer.Register(Configuration);//註冊配置 98 IoCContainer.Register(dbContextOption);//註冊數據庫配置信息 99 IoCContainer.Register(codeGenerateOption);//註冊代碼生成器相關配置信息 100 IoCContainer.Register(typeof(DefaultDbContext));//註冊EF上下文 101 IoCContainer.Register("Zxw.Framework.Website.Repositories", "Zxw.Framework.Website.IRepositories");//註冊倉儲 102 IoCContainer.Register("Zxw.Framework.Website.Services", "Zxw.Framework.Website.IServices");//註冊service 103 return IoCContainer.Build(services); 104 } 105 } 106 }
使用代碼生成器:
1 using System; 2 using System.Diagnostics; 3 using Microsoft.AspNetCore.Mvc; 4 using Zxw.Framework.NetCore.CodeGenerator; 5 using Zxw.Framework.NetCore.Helpers; 6 using Zxw.Framework.Website.IServices; 7 using Zxw.Framework.Website.ViewModels; 8 using Zxw.Framework.Website.Models; 9 10 namespace Zxw.Framework.Website.Controllers 11 { 12 public class HomeController : Controller 13 { 14 private ITutorClassTypeService iTutorClassTypeService; 15 16 public HomeController(ITutorClassTypeService tutorClassTypeService) 17 { 18 if(tutorClassTypeService==null) 19 throw new ArgumentNullException(nameof(tutorClassTypeService)); 20 iTutorClassTypeService = tutorClassTypeService; 21 } 22 public IActionResult Index() 23 { 24 CodeGenerator.Generate();//生成全部實體類對應的Repository和Service層代碼文件 25 CodeGenerator.GenerateSingle<TutorClassType, int>();//生成單個實體類對應的Repository和Service層代碼文件 26 27 return View(); 28 } 29 30 public IActionResult About() 31 { 32 ViewData["Message"] = "Your application description page."; 33 34 return View(); 35 } 36 37 public IActionResult Contact() 38 { 39 ViewData["Message"] = "Your contact page."; 40 41 return View(); 42 } 43 44 public IActionResult Error() 45 { 46 return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 47 } 48 49 protected override void Dispose(bool disposing) 50 { 51 if (disposing) 52 { 53 iTutorClassTypeService.Dispose(); 54 } 55 base.Dispose(disposing); 56 } 57 } 58 }
總結
寫博客真的很費力,但願本身可以堅持下去。
最後,歡迎各路大佬建議和拍磚~~
【懶人有道】在asp.net core中實現程序集註入
前言
1 // This method gets called by the runtime. Use this method to add services to the container. 2 public void ConfigureServices(IServiceCollection services) 3 { 4 //services.RegisterAssembly("IServices"); 5 services.AddSingleton<IUserService, UserService>(); 6 // Add framework services. 7 services.AddMvc(); 8 services.AddMvcCore() 9 .AddApiExplorer(); 10 services.AddSwaggerGen(options => 11 { 12 options.SwaggerDoc("v1", new Info() 13 { 14 Title = "Swagger測試", 15 Version = "v1", 16 Description = "Swagger測試RESTful API ", 17 TermsOfService = "None", 18 Contact = new Contact 19 { 20 Name = "來來吹牛逼", 21 Email = "xxoo123@outlook.com" 22 }, 23 }); 24 //設置xml註釋文檔,注意名稱必定要與項目名稱相同 25 var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "WebApi.xml"); 26 options.IncludeXmlComments(filePath); 27 }); 28 }
可是,隨着公司業務的擴大,系統項目的功能模塊急劇擴張,新增了不下百個或者千個Repository和Service(有點誇張了...),這時候如此單純滴注入就有點操蛋了。
打懶主意
試試就試試
- UserService --> IUserService
- UserRepository --> IUserRepository
- ......
- ClassName --> IClassName
1 /// <summary> 2 /// IServiceCollection擴展 3 /// </summary> 4 public static class ServiceExtension 5 { 6 /// <summary> 7 /// 用DI批量注入接口程序集中對應的實現類。 8 /// <para> 9 /// 須要注意的是,這裏有以下約定: 10 /// IUserService --> UserService, IUserRepository --> UserRepository. 11 /// </para> 12 /// </summary> 13 /// <param name="service"></param> 14 /// <param name="interfaceAssemblyName">接口程序集的名稱(不包含文件擴展名)</param> 15 /// <returns></returns> 16 public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName) 17 { 18 if (service == null) 19 throw new ArgumentNullException(nameof(service)); 20 if (string.IsNullOrEmpty(interfaceAssemblyName)) 21 throw new ArgumentNullException(nameof(interfaceAssemblyName)); 22 23 var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); 24 if (assembly == null) 25 { 26 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); 27 } 28 29 //過濾掉非接口及泛型接口 30 var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); 31 32 foreach (var type in types) 33 { 34 var implementTypeName = type.Name.Substring(1); 35 var implementType = RuntimeHelper.GetImplementType(implementTypeName, type); 36 if (implementType != null) 37 service.AddSingleton(type, implementType); 38 } 39 return service; 40 } 41 42 /// <summary> 43 /// 用DI批量注入接口程序集中對應的實現類。 44 /// </summary> 45 /// <param name="service"></param> 46 /// <param name="interfaceAssemblyName">接口程序集的名稱(不包含文件擴展名)</param> 47 /// <param name="implementAssemblyName">實現程序集的名稱(不包含文件擴展名)</param> 48 /// <returns></returns> 49 public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName) 50 { 51 if (service == null) 52 throw new ArgumentNullException(nameof(service)); 53 if(string.IsNullOrEmpty(interfaceAssemblyName)) 54 throw new ArgumentNullException(nameof(interfaceAssemblyName)); 55 if (string.IsNullOrEmpty(implementAssemblyName)) 56 throw new ArgumentNullException(nameof(implementAssemblyName)); 57 58 var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName); 59 if (interfaceAssembly == null) 60 { 61 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found"); 62 } 63 64 var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName); 65 if (implementAssembly == null) 66 { 67 throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found"); 68 } 69 70 //過濾掉非接口及泛型接口 71 var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType); 72 73 foreach (var type in types) 74 { 75 //過濾掉抽象類、泛型類以及非class 76 var implementType = implementAssembly.DefinedTypes 77 .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && 78 t.GetInterfaces().Any(b => b.Name == type.Name)); 79 if (implementType != null) 80 { 81 service.AddSingleton(type, implementType.AsType()); 82 } 83 } 84 85 return service; 86 } 87 }
附上RuntimeHelper.cs的代碼:
1 public class RuntimeHelper 2 { 3 /// <summary> 4 /// 獲取項目程序集,排除全部的系統程序集(Microsoft.***、System.***等)、Nuget下載包 5 /// </summary> 6 /// <returns></returns> 7 public static IList<Assembly> GetAllAssemblies() 8 { 9 var list = new List<Assembly>(); 10 var deps = DependencyContext.Default; 11 var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除全部的系統程序集、Nuget下載包 12 foreach (var lib in libs) 13 { 14 try 15 { 16 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)); 17 list.Add(assembly); 18 } 19 catch (Exception) 20 { 21 // ignored 22 } 23 } 24 return list; 25 } 26 27 public static Assembly GetAssembly(string assemblyName) 28 { 29 return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName)); 30 } 31 32 public static IList<Type> GetAllTypes() 33 { 34 var list = new List<Type>(); 35 foreach (var assembly in GetAllAssemblies()) 36 { 37 var typeInfos = assembly.DefinedTypes; 38 foreach (var typeInfo in typeInfos) 39 { 40 list.Add(typeInfo.AsType()); 41 } 42 } 43 return list; 44 } 45 46 public static IList<Type> GetTypesByAssembly(string assemblyName) 47 { 48 var list = new List<Type>(); 49 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName)); 50 var typeInfos = assembly.DefinedTypes; 51 foreach (var typeInfo in typeInfos) 52 { 53 list.Add(typeInfo.AsType()); 54 } 55 return list; 56 } 57 58 public static Type GetImplementType(string typeName, Type baseInterfaceType) 59 { 60 return GetAllTypes().FirstOrDefault(t => 61 { 62 if (t.Name == typeName && 63 t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name)) 64 { 65 var typeInfo = t.GetTypeInfo(); 66 return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType; 67 } 68 return false; 69 }); 70 } 71 }
好了,到此就基本完成了,記得在Startup.cs加上:
1 // This method gets called by the runtime. Use this method to add services to the container. 2 public IServiceProvider ConfigureServices(IServiceCollection services) 3 { 4 services.RegisterAssembly("IServices"); 5 6 // Add framework services. 7 services.AddMvc(); 8 }