添加项目文件。

master
冉成楼 2026-02-24 10:03:24 +08:00
commit 85b626b762
999 changed files with 219816 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

363
.gitignore vendored Normal file
View File

@ -0,0 +1,363 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@ -0,0 +1,226 @@
<%--
Author: yubaolee
Description: 用于生成OpenAuth.WebApi接口相关代码包括controller/app/实体/dbcontext
--%>
<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="Normal" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Assembly Name="Mono.Cecil" Path="..\Common" %>
<%@ Assembly Name="ICSharpCode.NRefactory" Path="..\Common" %>
<%@ Assembly Name="ICSharpCode.NRefactory.CSharp" Path="..\Common" %>
<%@ Assembly Src="Internal\Model.cs" %>
<%@ Assembly Src="Internal\Extensions.cs" %>
<%@ Assembly Src="Internal\Generator.cs" %>
<%@ Assembly Src="Internal\Parser.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="SchemaMapper" %>
<%@ Property Name="WholeDb"
Type="System.Boolean"
Category="1.Database"
Default="true"
Description="是否直接生成选定数据库中的所有表" %>
<%@ Property Name="HeaderModel"
Type="System.Boolean"
Category="1.Database"
Default="true"
Description="是否为启用头表模式,即类似‘入库订单’界面" %>
<%@ Property Name="SourceDatabase"
Type="SchemaExplorer.DatabaseSchema"
Category="1.Database"
Description="The source database." %>
<%@ Property Name="SourceTables"
Type="SchemaExplorer.TableSchemaCollection"
Category="1.Database" Description="可以选择一个或多个表使用Ctrl键" %>
<%@ Property Name="directory"
Type="System.String"
Default=".\"
Optional="True"
Description="代码生成路径"
Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
<%@ Property Name="ContextNamespace"
Type="System.String"
Category="2.Class"
Default="OpenAuth.Repository"
OnChanged="OnContextNamespaceChanged"
Description="DbContext默认命名空间尽量不要更改"%>
<%@ Property Name="EntityNamespace"
Type="System.String"
Default="OpenAuth.Repository.Domain"
Category="2.Class"
Description="实体默认命名空间,尽量不要更改"%>
<%@ Register Name="EntityGeneratedClass"
Template="Internal\Entity.Generated.cst"
MergeProperties="False" %>
<%@ Register Name="ContextGeneratedClass"
Template="Internal\Context.Generated.cst"
MergeProperties="True" %>
<%@ Register Name="ApplicationGenerateClass"
Template="ApiGenerate\Application.cst"
MergeProperties="False" %>
<%@ Register Name="RequestGenerateClass"
Template="ApiGenerate\Request.cst"
MergeProperties="False" %>
<%@ Register Name="ModifyReqGenerateClass"
Template="ApiGenerate\ModifyReq.cst"
MergeProperties="False" %>
<%@ Register Name="ControllerGenerateClass"
Template="ApiGenerate\Controller.cst"
MergeProperties="False" %>
开始创建OpenAuth.Core WebApi相关代码 ...
<% Generate(); %>
<script runat="template">
private TableSchemaCollection tables;
public void Generate()
{
Stopwatch watch = Stopwatch.StartNew();
string outputDirectory = Path.GetFullPath(directory);
if(WholeDb){
tables = SourceDatabase.Tables;
}
else{
tables = SourceTables;
}
CreateEntityClasses();
CreateControllerClass();
CreateApplicationClass();
CreateReqClass();
CreateContextClass();
watch.Stop();
Response.WriteLine("Generate Time: " + watch.ElapsedMilliseconds + " ms");
}
//创建实体类
public void CreateEntityClasses()
{
EntityGeneratedClass generatedClass = this.Create<EntityGeneratedClass>();
this.CopyPropertiesTo(generatedClass);
foreach(TableSchema table in tables)
{
string className = table.Name;
string generatedFile = Path.GetFullPath(directory) + "OpenAuth.Repository\\Domain\\" + className + ".cs";
generatedClass.Table = table;
Response.WriteLine("已生成"+generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
}
//创建DbContext
public void CreateContextClass()
{
ContextGeneratedClass generatedClass = this.Create<ContextGeneratedClass>();
this.CopyPropertiesTo(generatedClass);
string dbContextName;
if(WholeDb){
dbContextName = SourceDatabase.Name.ToSafeName();
}
else{
dbContextName = SourceTables.First().Database.Name.ToSafeName();
}
dbContextName = StringUtil.ToPascalCase(dbContextName);
string generatedFile = "OpenAuth.Repository\\" + dbContextName + "Context.cs";
Response.WriteLine("重要提示!!!!把下面内容添加到"+generatedFile+"对应的位置中,千万不要直接覆盖!!!");
Response.WriteLine(generatedClass.RenderToString());
}
//创建控制器,如UserManagerController.cs
public void CreateControllerClass()
{
ControllerGenerateClass generatedClass = this.Create<ControllerGenerateClass>();
this.CopyPropertiesTo(generatedClass);
foreach(TableSchema table in tables)
{
string generatedFile = Path.GetFullPath(directory) + "OpenAuth.WebApi\\Controllers\\"+ table.Name + "sController.cs";
generatedClass.ModuleName = table.Name;
Response.WriteLine("已生成"+generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
}
//创建APP层,如UserManagerApp.cs
public void CreateApplicationClass()
{
ApplicationGenerateClass generatedClass = this.Create<ApplicationGenerateClass>();
this.CopyPropertiesTo(generatedClass);
foreach(TableSchema table in tables)
{
string generatedFile = Path.GetFullPath(directory) + "OpenAuth.App\\"+ table.Name +"\\"+ table.Name + "App.cs";
generatedClass.Table = table;
//generatedClass.Entity = entity;
Response.WriteLine("已生成"+generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
}
//创建请求参数,如QueryUserListReq.cs
public void CreateReqClass()
{
RequestGenerateClass generatedClass = this.Create<RequestGenerateClass>();
this.CopyPropertiesTo(generatedClass);
foreach(TableSchema table in tables)
{
string generatedFile = Path.GetFullPath(directory) + "OpenAuth.App\\"+ table.Name +"\\Request\\Query"+ table.Name + "ListReq.cs";
generatedClass.ModuleName = table.Name;
Response.WriteLine("已生成"+generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
//生成编辑修改的请求参数
ModifyReqGenerateClass modifyReqGenerateClass = this.Create<ModifyReqGenerateClass>();
this.CopyPropertiesTo(modifyReqGenerateClass);
foreach(TableSchema table in tables)
{
string generatedFile = Path.GetFullPath(directory) + "OpenAuth.App\\"+ table.Name +"\\Request\\AddOrUpdate"+ table.Name + "Req.cs";
modifyReqGenerateClass.Table = table;
Response.WriteLine("已生成"+generatedFile);
modifyReqGenerateClass.RenderToFile(generatedFile, generatedFile, true);
}
}
private void OnContextNamespaceChanged(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(ContextNamespace))
return;
if (string.IsNullOrEmpty(EntityNamespace))
EntityNamespace = ContextNamespace + ".Domain";
}
</script>

View File

@ -0,0 +1,157 @@
<%--
Name: Database Table Properties
Author: yubaolee
Description: Create a list of properties from a database table
--%>
<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="True" Description="应用层" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Property Name="Table"
Type="SchemaExplorer.TableSchema" %>
<%@ Property Name="HeaderModel"
Type="System.Boolean"
Category="1.Database"
Default="true"
Description="是否为启用头表模式,即类似‘入库订单’界面" %>
<%@ Assembly Src="../Web/Util.cs" %>
<%@ Import Namespace="Util" %>
using System;
using System.Linq;
using Infrastructure;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Interface;
namespace OpenAuth.App
{
public class <%=Table.Name%>App : BaseStringApp<<%=Table.Name%>, OpenAuthDBContext>
{
private RevelanceManagerApp _revelanceApp;
/// <summary>
/// 加载列表
/// </summary>
public TableData Load(Query<%=Table.Name%>ListReq request)
{
var loginContext = _auth.GetCurrentUser();
if (loginContext == null)
{
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
}
//如果是WebAPI,请务必改为loginContext.GetTableColumns("<%=Table.Name%>");
var columnFields = loginContext.GetTableColumnsFromDb("<%=Table.Name%>");
if (columnFields == null || columnFields.Count == 0)
{
throw new Exception("请在代码生成界面配置Category表的字段属性");
}
var result = new TableData();
var objs = UnitWork.Find<<%=Table.Name%>>(null);
if (!string.IsNullOrEmpty(request.key))
{
objs = objs.Where(u => u.Id.Contains(request.key));
}
var propertyStr = string.Join(',', columnFields.Select(u =>u.ColumnName));
result.columnFields = columnFields;
result.data = objs.OrderBy(u => u.Id)
.Skip((request.page - 1) * request.limit)
.Take(request.limit).Select($"new ({propertyStr})");
result.count = objs.Count();
return result;
}
<%
if(Table.Name.Contains("Tbl") && (!Table.Name.Contains("Dtbl")) && this.HeaderModel){
var dtblName = Table.Name.Replace("Tbl","Dtbl"); //明细表的表名
%>
public void Add(AddOrUpdate<%=Table.Name%>Req req)
{
var obj = req.MapTo<<%=Table.Name%>>();
//todo:根据自己的业务场景,补充或调整字段
obj.CreateTime = DateTime.Now;
var user = _auth.GetCurrentUser().User;
obj.CreateUserId = user.Id;
obj.CreateUserName = user.Name;
UnitWork.Add(obj);
if (req.<%=dtblName%>Reqs != null && req.<%=dtblName%>Reqs.Any())
{
foreach (var detail in req.<%=dtblName%>Reqs)
{
detail.ForeignKeyId = obj.Id; //todo:调整自己的明细表外键
_<%=dtblName%>App.AddNoSave(detail);
}
}
UnitWork.Save();
}
public void Update(AddOrUpdate<%=Table.Name%>Req obj)
{
var user = _auth.GetCurrentUser().User;
if (obj.<%=dtblName%>Reqs != null && obj.<%=dtblName%>Reqs.Any())
{
//id为空的添加
foreach (var detail in obj.<%=dtblName%>Reqs.Where(u =>string.IsNullOrEmpty(u.Id)))
{
detail.ForeignKeyId = obj.Id; //todo:调整自己的明细表外键
_<%=dtblName%>App.AddNoSave(detail);
}
//id比数据库少的删除
var containids = obj.<%=dtblName%>Reqs.Select(u => u.Id)
.Where(u =>!string.IsNullOrEmpty(u)).ToList();
if (containids.Any())
{
UnitWork.Delete<<%=dtblName%>>(u =>(!containids.Contains(u.Id)) && u.ForeignKeyId == obj.Id); //todo:调整自己的明细表外键
}
//更新id相同的
foreach (var detail in obj.<%=dtblName%>Reqs.Where(u =>!string.IsNullOrEmpty(u.Id)))
{
_<%=dtblName%>App.Update(detail);
}
}
<%CreateUpdate();%>
UnitWork.Save();
}
<%
}else{ %>
public void Add(AddOrUpdate<%=Table.Name%>Req req)
{
var obj = req.MapTo<<%=Table.Name%>>();
//todo:根据自己的业务场景,补充或调整字段
//比如obj.CreateTime = DateTime.Now;
// var user = _auth.GetCurrentUser().User;
// obj.CreateUserId = user.Id;
// obj.CreateUserName = user.Name;
Repository.Add(obj);
}
public void Update(AddOrUpdate<%=Table.Name%>Req obj)
{
<%CreateUpdate();%>
}
<%
}
%>
public <%=Table.Name%>App(IUnitWork<OpenAuthDBContext> unitWork, IRepository<<%=Table.Name%>, OpenAuthDBContext> repository,
RevelanceManagerApp app, IAuth auth) : base(unitWork, repository,auth)
{
_revelanceApp = app;
}
}
}
<script runat="template">
/// <summary>
/// 创建更新字段
/// </summary>
public void CreateUpdate() {
var updatestr = Tools.CreateBlank(1) + "UnitWork.Update<" + Table.Name + ">(u => u.Id == obj.Id, u => new " + Table.Name + "\r\n";
updatestr +=Tools.CreateBlank(1) + "{\r\n";
var columnstr = "";
foreach (ColumnSchema p in Table.Columns) {
if (p.IsPrimaryKeyMember) continue ;
columnstr += Tools.CreateBlank(2)+ p.Name + " = obj." + p.Name + ", \r\n";
}
columnstr = columnstr.Substring(0, columnstr.Length - 4); //删除最后一个逗号
updatestr += columnstr;
updatestr += "\r\n" +Tools.CreateBlank(2) +"//todo:根据自己的业务场景,补充或调整字段";
updatestr += "\r\n" +Tools.CreateBlank(1) +"});";
Response.WriteLine(updatestr);
}
</script>

View File

@ -0,0 +1,128 @@
<%--
Name: Database Table Properties
Author: yubaolee
Description: Create a list of properties from a database table
--%>
<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="True" Description="控制器" %>
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
using System;
using Infrastructure;
using Microsoft.AspNetCore.Mvc;
using OpenAuth.App;
using OpenAuth.App.Request;
using OpenAuth.App.Response;
using OpenAuth.Repository.Domain;
namespace OpenAuth.WebApi.Controllers
{
/// <summary>
/// <%=ModuleName%>操作
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class <%=ModuleName%>sController : ControllerBase
{
private readonly <%=ModuleName%>App _app;
/// <summary>
/// //获取详情
/// </summary>
[HttpGet]
public Response<<%=ModuleName%>> Get(string id)
{
var result = new Response<<%=ModuleName%>>();
try
{
result.Result = _app.Get(id);
}
catch (Exception ex)
{
result.Code = 500;
result.Message = ex.InnerException?.Message ?? ex.Message;
}
return result;
}
/// <summary>
/// 添加
/// </summary>
[HttpPost]
public Response Add(AddOrUpdate<%=ModuleName%>Req obj)
{
var result = new Response();
try
{
_app.Add(obj);
}
catch (Exception ex)
{
result.Code = 500;
result.Message = ex.InnerException?.Message ?? ex.Message;
}
return result;
}
/// <summary>
/// 修改
/// </summary>
[HttpPost]
public Response Update(AddOrUpdate<%=ModuleName%>Req obj)
{
var result = new Response();
try
{
_app.Update(obj);
}
catch (Exception ex)
{
result.Code = 500;
result.Message = ex.InnerException?.Message ?? ex.Message;
}
return result;
}
/// <summary>
/// 加载列表
/// </summary>
[HttpGet]
public TableData Load([FromQuery]Query<%=ModuleName%>ListReq request)
{
return _app.Load(request);
}
/// <summary>
/// 批量删除
/// </summary>
[HttpPost]
public Response Delete([FromBody]string[] ids)
{
var result = new Response();
try
{
_app.Delete(ids);
}
catch (Exception ex)
{
result.Code = 500;
result.Message = ex.InnerException?.Message ?? ex.Message;
}
return result;
}
public <%=ModuleName%>sController(<%=ModuleName%>App app)
{
_app = app;
}
}
}

View File

@ -0,0 +1,66 @@
<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
<%@ Assembly Src="../Internal/Model.cs" %>
<%@ Assembly Src="../Internal/Extensions.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Import Namespace="SchemaMapper" %>
<%@ Property Name="Table"
Type="SchemaExplorer.TableSchema" %>
<%@ Property Name="HeaderModel"
Type="System.Boolean"
Category="1.Database"
Default="true"
Description="是否为启用头表模式,即类似‘入库订单’界面" %>
<%@ Property Name="EntityNamespace"
Type="System.String" %>
//------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a CodeSmith Template.
//
// DO NOT MODIFY contents of this file. Changes to this
// file will be lost if the code is regenerated.
// Author:Yubao Li
// </autogenerated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
using OpenAuth.Repository.Core;
namespace OpenAuth.App.Request
{
/// <summary>
/// <%= Table.Description %>
/// </summary>
[Table("<%= Table.Name%>")]
public partial class AddOrUpdate<%= Table.Name %>Req
{
<% foreach(ColumnSchema p in Table.Columns) {
%>
/// <summary>
/// <%=p.Description %>
/// </summary>
public <%= p.SystemType.ToNullableType(p.AllowDBNull == true) %> <%= p.Name%> { get; set; }
<% } %>
//todo:根据自己的业务场景添加需要的字段
<%
if(Table.Name.Contains("Tbl") && (!Table.Name.Contains("Dtbl")) && this.HeaderModel){
var dtblName = Table.Name.Replace("Tbl","Dtbl"); //明细表的表名
%>
public List<AddOrUpdate<%=dtblName%>Req> <%=dtblName%>Reqs { get; set; }
<% } %>
}
}

View File

@ -0,0 +1,17 @@
<%--
Name: Database Table Properties
Author: yubaolee
Description: Create a list of properties from a database table
--%>
<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="False" Description="应用层" %>
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
namespace OpenAuth.App.Request
{
public class Query<%=ModuleName%>ListReq : PageReq
{
//todo:根据自己的业务场景添加需要的字段
}
}

View File

@ -0,0 +1,81 @@
<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
<%@ Assembly Src="../Internal/Model.cs" %>
<%@ Assembly Src="../Internal/Extensions.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Import Namespace="SchemaMapper" %>
<%@ Property Name="WholeDb"
Type="System.Boolean"
Category="1.Database"
Default="true"
Description="是否为整个数据库" %>
<%@ Property Name="SourceDatabase"
Type="SchemaExplorer.DatabaseSchema"
Category="1.Database"
Description="The source database." %>
<%@ Property Name="SourceTables"
Type="SchemaExplorer.TableSchemaCollection"
Category="1.Database" Description="选择部分表" %>
<%@ Property Name="ContextNamespace" Type="System.String" %>
<%@ Property Name="EntityNamespace" Type="System.String" %>
using Microsoft.EntityFrameworkCore;
using <%= EntityNamespace %>;
namespace <%= ContextNamespace %>
{
<%
string dbContextName;
if(WholeDb){
dbContextName = SourceDatabase.Name.ToSafeName();
}
else{
dbContextName = SourceTables.First().Database.Name.ToSafeName();
}
dbContextName = StringUtil.ToPascalCase(dbContextName);
Response.WriteLine(" public partial class "+ dbContextName +"Context: DbContext");
%>
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//当主键为联合主键时,需要把这里的内容拷贝到对应的位置
<%
TableSchemaCollection tables;
if(WholeDb){
tables = SourceDatabase.Tables;
}
else{
tables = SourceTables;
}
foreach(TableSchema table in tables)
{
if(table.PrimaryKeys.Count <=1) continue;
var keys = string.Join(",", table.Columns.Where(u=>u.IsPrimaryKeyMember==true)
.Select(u =>"c."+u.Name));
Response.WriteLine(" modelBuilder.Entity<"+table.Name+">()");
Response.WriteLine(" .HasKey(c => new { "+keys+" });");
}
%>
}
<%
foreach(TableSchema table in tables)
{
Response.WriteLine(" public virtual DbSet<"+table.Name+"> "+StringUtil.ToPascalCase(StringUtil.ToPlural(table.Name))+" { get; set; }");
}
%>
}
}

View File

@ -0,0 +1,75 @@
<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
<%@ Assembly Src="../Internal/Model.cs" %>
<%@ Assembly Src="../Internal/Extensions.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Import Namespace="SchemaMapper" %>
<%@ Property Name="Table"
Type="SchemaExplorer.TableSchema" %>
<%@ Property Name="EntityNamespace"
Type="System.String" %>
//------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a CodeSmith Template.
//
// DO NOT MODIFY contents of this file. Changes to this
// file will be lost if the code is regenerated.
// Author:Yubao Li
// </autogenerated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
using OpenAuth.Repository.Core;
namespace <%= EntityNamespace %>
{
/// <summary>
/// <%= Table.Description %>
/// </summary>
[Table("<%= Table.Name%>")]
public partial class <%= Table.Name %> : StringEntity
{
public <%= Table.Name %>()
{
<% foreach(ColumnSchema p in Table.Columns) {
if(p.IsPrimaryKeyMember) continue;
string type = p.SystemType.ToNullableType(p.AllowDBNull == true);
if(type =="int" || type=="decimal")
Response.WriteLine(" this."+p.Name+"= 0;");
else if(type =="string")
Response.WriteLine(" this."+p.Name+"= string.Empty;");
else if(type.ToLower().Contains("datetime"))
Response.WriteLine(" this."+p.Name+"= DateTime.Now;");
} // foreach %>
}
<%
foreach(ColumnSchema p in Table.Columns) {
if(p.IsPrimaryKeyMember) continue;
%>
/// <summary>
/// <%=p.Description %>
/// </summary>
[Description("<%=p.Description%>")]
<%if(p.Name.LastIndexOf("Id") != -1){%>
[Browsable(false)]
<%}%>
<%if(p.DataType == DbType.Byte){%>
public bool <%= p.Name%> { get; set; }
<%}else{%>
public <%= p.SystemType.ToNullableType(p.AllowDBNull == true) %> <%= p.Name%> { get; set; }
<%}%>
<% } // foreach %>
}
}

View File

@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CodeSmith.Engine;
namespace SchemaMapper
{
public enum CodeLanguage
{
CSharp,
VisualBasic
}
public static class Extensions
{
private static readonly HashSet<string> _csharpKeywords;
private static readonly HashSet<string> _visualBasicKeywords;
private static readonly Dictionary<string, string> _csharpTypeAlias;
static Extensions()
{
_csharpKeywords = new HashSet<string>(StringComparer.Ordinal)
{
"as", "do", "if", "in", "is",
"for", "int", "new", "out", "ref", "try",
"base", "bool", "byte", "case", "char", "else", "enum", "goto", "lock", "long", "null", "this", "true", "uint", "void",
"break", "catch", "class", "const", "event", "false", "fixed", "float", "sbyte", "short", "throw", "ulong", "using", "while",
"double", "extern", "object", "params", "public", "return", "sealed", "sizeof", "static", "string", "struct", "switch", "typeof", "unsafe", "ushort",
"checked", "decimal", "default", "finally", "foreach", "private", "virtual",
"abstract", "continue", "delegate", "explicit", "implicit", "internal", "operator", "override", "readonly", "volatile",
"__arglist", "__makeref", "__reftype", "interface", "namespace", "protected", "unchecked",
"__refvalue", "stackalloc"
};
_visualBasicKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"as", "do", "if", "in", "is", "me", "of", "on", "or", "to",
"and", "dim", "end", "for", "get", "let", "lib", "mod", "new", "not", "rem", "set", "sub", "try", "xor",
"ansi", "auto", "byte", "call", "case", "cdbl", "cdec", "char", "cint", "clng", "cobj", "csng", "cstr", "date", "each", "else",
"enum", "exit", "goto", "like", "long", "loop", "next", "step", "stop", "then", "true", "wend", "when", "with",
"alias", "byref", "byval", "catch", "cbool", "cbyte", "cchar", "cdate", "class", "const", "ctype", "cuint", "culng", "endif", "erase", "error",
"event", "false", "gosub", "isnot", "redim", "sbyte", "short", "throw", "ulong", "until", "using", "while",
"csbyte", "cshort", "double", "elseif", "friend", "global", "module", "mybase", "object", "option", "orelse", "public", "resume", "return", "select", "shared",
"single", "static", "string", "typeof", "ushort",
"andalso", "boolean", "cushort", "decimal", "declare", "default", "finally", "gettype", "handles", "imports", "integer", "myclass", "nothing", "partial", "private", "shadows",
"trycast", "unicode", "variant",
"assembly", "continue", "delegate", "function", "inherits", "operator", "optional", "preserve", "property", "readonly", "synclock", "uinteger", "widening",
"addressof", "interface", "namespace", "narrowing", "overloads", "overrides", "protected", "structure", "writeonly",
"addhandler", "directcast", "implements", "paramarray", "raiseevent", "withevents",
"mustinherit", "overridable",
"mustoverride",
"removehandler",
"class_finalize", "notinheritable", "notoverridable",
"class_initialize"
};
_csharpTypeAlias = new Dictionary<string, string>(16)
{
{"System.Int16", "short"},
{"System.Int32", "int"},
{"System.Int64", "long"},
{"System.String", "string"},
{"System.Object", "object"},
{"System.Boolean", "bool"},
{"System.Void", "void"},
{"System.Char", "char"},
{"System.Byte", "byte"},
{"System.UInt16", "ushort"},
{"System.UInt32", "uint"},
{"System.UInt64", "ulong"},
{"System.SByte", "sbyte"},
{"System.Single", "float"},
{"System.Double", "double"},
{"System.Decimal", "decimal"}
};
}
public static string ToCamelCase(this string name)
{
return StringUtil.ToCamelCase(name);
}
public static string ToPascalCase(this string name)
{
return StringUtil.ToPascalCase(name);
}
public static string ToFieldName(this string name)
{
return "_" + StringUtil.ToCamelCase(name);
}
public static string MakeUnique(this string name, Func<string, bool> exists)
{
string uniqueName = name;
int count = 1;
while (exists(uniqueName))
uniqueName = string.Concat(name, count++);
return uniqueName;
}
public static bool IsKeyword(this string text, CodeLanguage language = CodeLanguage.CSharp)
{
return language == CodeLanguage.VisualBasic
? _visualBasicKeywords.Contains(text)
: _csharpKeywords.Contains(text);
}
public static string ToSafeName(this string name, CodeLanguage language = CodeLanguage.CSharp)
{
if (!name.IsKeyword(language))
return name;
return language == CodeLanguage.VisualBasic
? string.Format("[{0}]", name)
: "@" + name;
}
public static string ToType(this Type type, CodeLanguage language = CodeLanguage.CSharp)
{
return ToType(type.FullName, language);
}
public static string ToType(this string type, CodeLanguage language = CodeLanguage.CSharp)
{
if (type == "System.Xml.XmlDocument")
type = "System.String";
string t;
if (language == CodeLanguage.CSharp && _csharpTypeAlias.TryGetValue(type, out t))
return t;
return type;
}
public static string ToNullableType(this Type type, bool isNullable = false, CodeLanguage language = CodeLanguage.CSharp)
{
return ToNullableType(type.FullName, isNullable, language);
}
public static string ToNullableType(this string type, bool isNullable = false, CodeLanguage language = CodeLanguage.CSharp)
{
bool isValueType = type.IsValueType();
type = type.ToType(language);
if (!isValueType || !isNullable)
return type;
return language == CodeLanguage.VisualBasic
? string.Format("Nullable(Of {0})", type)
: type + "?";
}
public static bool IsValueType(this string type)
{
if (!type.StartsWith("System."))
return false;
var t = Type.GetType(type, false);
return t != null && t.IsValueType;
}
public static string ToDelimitedString(this IEnumerable<string> values, string delimiter, string format = null)
{
var sb = new StringBuilder();
foreach (var i in values)
{
if (sb.Length > 0)
sb.Append(delimiter);
if (string.IsNullOrEmpty(format))
sb.Append(i);
else
sb.AppendFormat(format, i);
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,837 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using CodeSmith.Engine;
using SchemaExplorer;
namespace SchemaMapper
{
public enum TableNaming
{
Mixed = 0,
Plural = 1,
Singular = 2
}
public enum EntityNaming
{
Preserve = 0,
Plural = 1,
Singular = 2
}
public enum RelationshipNaming
{
None = 0,
Plural = 1,
ListSuffix = 2
}
public enum ContextNaming
{
Preserve = 0,
Plural = 1,
TableSuffix = 2
}
public class GeneratorSettings
{
public GeneratorSettings()
{
RelationshipNaming = RelationshipNaming.ListSuffix;
EntityNaming = EntityNaming.Singular;
TableNaming = TableNaming.Singular;
CleanExpressions = new List<string> { @"^\d+" };
IgnoreExpressions = new List<string>();
}
public TableNaming TableNaming { get; set; }
public EntityNaming EntityNaming { get; set; }
public RelationshipNaming RelationshipNaming { get; set; }
public ContextNaming ContextNaming { get; set; }
public List<string> IgnoreExpressions { get; set; }
public List<string> CleanExpressions { get; set; }
public bool InclusionMode { get; set; }
public bool IsIgnored(string name)
{
if (IgnoreExpressions.Count == 0)
return false;
bool isMatch = IgnoreExpressions.Any(regex => Regex.IsMatch(name, regex));
return InclusionMode ? !isMatch : isMatch;
}
public string CleanName(string name)
{
if (CleanExpressions.Count == 0)
return name;
foreach (var regex in CleanExpressions.Where(r => !string.IsNullOrEmpty(r)))
if (Regex.IsMatch(name, regex))
return Regex.Replace(name, regex, "");
return name;
}
public string RelationshipName(string name)
{
if (RelationshipNaming == RelationshipNaming.None)
return name;
if (RelationshipNaming == RelationshipNaming.ListSuffix)
return name + "List";
return StringUtil.ToPascalCase(StringUtil.ToPlural(name));
}
public string ContextName(string name)
{
if (ContextNaming == ContextNaming.Preserve)
return name;
if (ContextNaming == ContextNaming.TableSuffix)
return name + "Table";
return StringUtil.ToPascalCase(StringUtil.ToPlural(name));
}
public string EntityName(string name)
{
if (TableNaming != TableNaming.Plural && EntityNaming == EntityNaming.Plural)
name = StringUtil.ToPlural(name);
else if (TableNaming != TableNaming.Singular && EntityNaming == EntityNaming.Singular)
name = StringUtil.ToSingular(name);
return StringUtil.ToPascalCase(name);
}
}
public class SchemaItemProcessedEventArgs : EventArgs
{
public SchemaItemProcessedEventArgs(string name)
{
_name = name;
}
private readonly string _name;
public string Name
{
get { return _name; }
}
}
public class UniqueNamer
{
private readonly ConcurrentDictionary<string, HashSet<string>> _names;
public UniqueNamer()
{
_names = new ConcurrentDictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
Comparer = StringComparer.CurrentCulture;
// add existing
UniqueContextName("ChangeTracker");
UniqueContextName("Configuration");
UniqueContextName("Database");
UniqueContextName("InternalContext");
}
public IEqualityComparer<string> Comparer { get; set; }
public string UniqueName(string bucketName, string name)
{
var hashSet = _names.GetOrAdd(bucketName, k => new HashSet<string>(Comparer));
string result = name.MakeUnique(hashSet.Contains);
hashSet.Add(result);
return result;
}
public string UniqueClassName(string className)
{
const string globalClassName = "global::ClassName";
return UniqueName(globalClassName, className);
}
public string UniqueContextName(string name)
{
const string globalContextname = "global::ContextName";
return UniqueName(globalContextname, name);
}
public string UniqueRelationshipName(string name)
{
const string globalContextname = "global::RelationshipName";
return UniqueName(globalContextname, name);
}
}
public class Generator
{
private readonly UniqueNamer _namer;
public Generator()
{
_settings = new GeneratorSettings();
_namer = new UniqueNamer();
}
public event EventHandler<SchemaItemProcessedEventArgs> SchemaItemProcessed;
protected void OnSchemaItemProcessed(string name)
{
var handler = SchemaItemProcessed;
if (handler == null)
return;
handler(this, new SchemaItemProcessedEventArgs(name));
}
private readonly GeneratorSettings _settings;
public GeneratorSettings Settings
{
get { return _settings; }
}
//按表信息创建DbContext
public EntityContext Generate(TableSchema tableSchema)
{
// only DeepLoad when in ignore mode
tableSchema.DeepLoad = !Settings.InclusionMode;
var entityContext = new EntityContext();
entityContext.DatabaseName = tableSchema.Database.Name;
string dataContextName = StringUtil.ToPascalCase(tableSchema.Database.Name) + "Context";
dataContextName = _namer.UniqueClassName(dataContextName);
entityContext.ClassName = dataContextName;
GetEntity(entityContext, tableSchema);
return entityContext;
}
//按数据库连接信息创建DbContext
public EntityContext Generate(DatabaseSchema databaseSchema)
{
// only DeepLoad when in ignore mode
databaseSchema.DeepLoad = !Settings.InclusionMode;
var entityContext = new EntityContext();
entityContext.DatabaseName = databaseSchema.Name;
string dataContextName = StringUtil.ToPascalCase(databaseSchema.Name) + "Context";
dataContextName = _namer.UniqueClassName(dataContextName);
entityContext.ClassName = dataContextName;
foreach (TableSchema t in databaseSchema.Tables)
{
if (Settings.IsIgnored(t.FullName))
{
Debug.WriteLine("Skipping Table: " + t.FullName);
}
else if (IsManyToMany(t))
{
CreateManyToMany(entityContext, t);
}
else
{
Debug.WriteLine("Getting Table Schema: " + t.FullName);
GetEntity(entityContext, t);
}
OnSchemaItemProcessed(t.FullName);
}
return entityContext;
}
//根据DbContext和tableSchema获取实体
public Entity GetEntity(EntityContext entityContext, TableSchema tableSchema, bool processRelationships = true, bool processMethods = true)
{
string key = tableSchema.FullName;
Entity entity = entityContext.Entities.ByTable(key)
?? CreateEntity(entityContext, tableSchema);
if (!entity.Properties.IsProcessed)
CreateProperties(entity, tableSchema);
if (processRelationships && !entity.Relationships.IsProcessed)
CreateRelationships(entityContext, entity, tableSchema);
if (processMethods && !entity.Methods.IsProcessed)
CreateMethods(entity, tableSchema);
entity.IsProcessed = true;
return entity;
}
private Entity CreateEntity(EntityContext entityContext, TableSchema tableSchema)
{
var entity = new Entity
{
FullName = tableSchema.FullName,
TableName = tableSchema.Name,
TableSchema = tableSchema.Owner,
Description = tableSchema.Description
};
string className = ToClassName(tableSchema.Name);
className = _namer.UniqueClassName(className);
string mappingName = className + "Map";
mappingName = _namer.UniqueClassName(mappingName);
string contextName = Settings.ContextName(className);
contextName = ToPropertyName(entityContext.ClassName, contextName);
contextName = _namer.UniqueContextName(contextName);
entity.ClassName = className;
entity.ContextName = contextName;
entity.MappingName = mappingName;
entityContext.Entities.Add(entity);
return entity;
}
/// <summary>
/// 创建实体的属性
/// </summary>
private void CreateProperties(Entity entity, TableSchema tableSchema)
{
foreach (ColumnSchema columnSchema in tableSchema.Columns)
{
// skip unsupported type
if (columnSchema.NativeType.Equals("hierarchyid", StringComparison.OrdinalIgnoreCase)
|| columnSchema.NativeType.Equals("sql_variant", StringComparison.OrdinalIgnoreCase))
{
Debug.WriteLine(string.Format("Skipping column '{0}' because it has an unsupported db type '{1}'.",
columnSchema.Name, columnSchema.NativeType));
continue;
}
Property property = entity.Properties.ByColumn(columnSchema.Name);
if (property == null)
{
property = new Property { ColumnName = columnSchema.Name };
entity.Properties.Add(property);
}
string propertyName = ToPropertyName(entity.ClassName, columnSchema.Name);
propertyName = _namer.UniqueName(entity.ClassName, propertyName);
property.PropertyName = propertyName;
property.DataType = columnSchema.DataType;
property.SystemType = columnSchema.SystemType;
property.NativeType = columnSchema.NativeType;
property.Description = columnSchema.Description;
property.IsPrimaryKey = columnSchema.IsPrimaryKeyMember;
property.IsForeignKey = columnSchema.IsForeignKeyMember;
property.IsNullable = columnSchema.AllowDBNull;
property.IsIdentity = IsIdentity(columnSchema);
property.IsRowVersion = IsRowVersion(columnSchema);
property.IsAutoGenerated = IsDbGenerated(columnSchema);
if (columnSchema.IsUnique)
property.IsUnique = columnSchema.IsUnique;
if (property.SystemType == typeof(string)
|| property.SystemType == typeof(byte[]))
{
property.MaxLength = columnSchema.Size;
}
if (property.SystemType == typeof(float)
|| property.SystemType == typeof(double)
|| property.SystemType == typeof(decimal))
{
property.Precision = columnSchema.Precision;
property.Scale = columnSchema.Scale;
}
property.IsProcessed = true;
}
entity.Properties.IsProcessed = true;
}
private void CreateRelationships(EntityContext entityContext, Entity entity, TableSchema tableSchema)
{
foreach (TableKeySchema tableKey in tableSchema.ForeignKeys)
{
if (Settings.IsIgnored(tableKey.ForeignKeyTable.FullName)
|| Settings.IsIgnored(tableKey.PrimaryKeyTable.FullName))
{
Debug.WriteLine("Skipping relationship '{0}' because table '{1}' or '{2}' is ignored.",
tableKey.FullName, tableKey.ForeignKeyTable.FullName, tableKey.PrimaryKeyTable.FullName);
continue;
}
CreateRelationship(entityContext, entity, tableKey);
}
entity.Relationships.IsProcessed = true;
}
private void CreateRelationship(EntityContext entityContext, Entity foreignEntity, TableKeySchema tableKeySchema)
{
Entity primaryEntity = GetEntity(entityContext, tableKeySchema.PrimaryKeyTable, false, false);
string primaryName = primaryEntity.ClassName;
string foreignName = foreignEntity.ClassName;
string relationshipName = tableKeySchema.Name;
relationshipName = _namer.UniqueRelationshipName(relationshipName);
bool isCascadeDelete = IsCascadeDelete(tableKeySchema);
bool foreignMembersRequired;
bool primaryMembersRequired;
var foreignMembers = GetKeyMembers(foreignEntity, tableKeySchema.ForeignKeyMemberColumns, tableKeySchema.Name, out foreignMembersRequired);
var primaryMembers = GetKeyMembers(primaryEntity, tableKeySchema.PrimaryKeyMemberColumns, tableKeySchema.Name, out primaryMembersRequired);
Relationship foreignRelationship = foreignEntity.Relationships
.FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey);
if (foreignRelationship == null)
{
foreignRelationship = new Relationship { RelationshipName = relationshipName };
foreignEntity.Relationships.Add(foreignRelationship);
}
foreignRelationship.IsMapped = true;
foreignRelationship.IsForeignKey = true;
foreignRelationship.ThisCardinality = foreignMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne;
foreignRelationship.ThisEntity = foreignName;
foreignRelationship.ThisProperties = new List<string>(foreignMembers);
foreignRelationship.OtherEntity = primaryName;
foreignRelationship.OtherProperties = new List<string>(primaryMembers);
foreignRelationship.CascadeDelete = isCascadeDelete;
string prefix = GetMemberPrefix(foreignRelationship, primaryName, foreignName);
string foreignPropertyName = ToPropertyName(foreignEntity.ClassName, prefix + primaryName);
foreignPropertyName = _namer.UniqueName(foreignEntity.ClassName, foreignPropertyName);
foreignRelationship.ThisPropertyName = foreignPropertyName;
// add reverse
Relationship primaryRelationship = primaryEntity.Relationships
.FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey == false);
if (primaryRelationship == null)
{
primaryRelationship = new Relationship { RelationshipName = relationshipName };
primaryEntity.Relationships.Add(primaryRelationship);
}
primaryRelationship.IsMapped = false;
primaryRelationship.IsForeignKey = false;
primaryRelationship.ThisEntity = primaryName;
primaryRelationship.ThisProperties = new List<string>(primaryMembers);
primaryRelationship.OtherEntity = foreignName;
primaryRelationship.OtherProperties = new List<string>(foreignMembers);
primaryRelationship.CascadeDelete = isCascadeDelete;
bool isOneToOne = IsOneToOne(tableKeySchema, foreignRelationship);
if (isOneToOne)
primaryRelationship.ThisCardinality = primaryMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne;
else
primaryRelationship.ThisCardinality = Cardinality.Many;
string primaryPropertyName = prefix + foreignName;
if (!isOneToOne)
primaryPropertyName = Settings.RelationshipName(primaryPropertyName);
primaryPropertyName = ToPropertyName(primaryEntity.ClassName, primaryPropertyName);
primaryPropertyName = _namer.UniqueName(primaryEntity.ClassName, primaryPropertyName);
primaryRelationship.ThisPropertyName = primaryPropertyName;
foreignRelationship.OtherPropertyName = primaryRelationship.ThisPropertyName;
foreignRelationship.OtherCardinality = primaryRelationship.ThisCardinality;
primaryRelationship.OtherPropertyName = foreignRelationship.ThisPropertyName;
primaryRelationship.OtherCardinality = foreignRelationship.ThisCardinality;
foreignRelationship.IsProcessed = true;
primaryRelationship.IsProcessed = true;
}
private void CreateManyToMany(EntityContext entityContext, TableSchema joinTable)
{
if (joinTable.ForeignKeys.Count != 2)
return;
var joinTableName = joinTable.Name;
var joinSchemaName = joinTable.Owner;
// first fkey is always left, second fkey is right
var leftForeignKey = joinTable.ForeignKeys[0];
var leftTable = leftForeignKey.PrimaryKeyTable;
var joinLeftColumn = leftForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList();
var leftEntity = GetEntity(entityContext, leftTable, false, false);
var rightForeignKey = joinTable.ForeignKeys[1];
var rightTable = rightForeignKey.PrimaryKeyTable;
var joinRightColumn = rightForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList();
var rightEntity = GetEntity(entityContext, rightTable, false, false);
string leftPropertyName = Settings.RelationshipName(rightEntity.ClassName);
leftPropertyName = _namer.UniqueName(leftEntity.ClassName, leftPropertyName);
string rightPropertyName = Settings.RelationshipName(leftEntity.ClassName);
rightPropertyName = _namer.UniqueName(rightEntity.ClassName, rightPropertyName);
string relationshipName = string.Format("{0}|{1}",
leftForeignKey.Name,
rightForeignKey.Name);
relationshipName = _namer.UniqueRelationshipName(relationshipName);
var left = new Relationship { RelationshipName = relationshipName };
left.IsForeignKey = false;
left.IsMapped = true;
left.ThisCardinality = Cardinality.Many;
left.ThisEntity = leftEntity.ClassName;
left.ThisPropertyName = leftPropertyName;
left.OtherCardinality = Cardinality.Many;
left.OtherEntity = rightEntity.ClassName;
left.OtherPropertyName = rightPropertyName;
left.JoinTable = joinTableName;
left.JoinSchema = joinSchemaName;
left.JoinThisColumn = new List<string>(joinLeftColumn);
left.JoinOtherColumn = new List<string>(joinRightColumn);
leftEntity.Relationships.Add(left);
var right = new Relationship { RelationshipName = relationshipName };
right.IsForeignKey = false;
right.IsMapped = false;
right.ThisCardinality = Cardinality.Many;
right.ThisEntity = rightEntity.ClassName;
right.ThisPropertyName = rightPropertyName;
right.OtherCardinality = Cardinality.Many;
right.OtherEntity = leftEntity.ClassName;
right.OtherPropertyName = leftPropertyName;
right.JoinTable = joinTableName;
right.JoinSchema = joinSchemaName;
right.JoinThisColumn = new List<string>(joinRightColumn);
right.JoinOtherColumn = new List<string>(joinLeftColumn);
rightEntity.Relationships.Add(right);
}
private void CreateMethods(Entity entity, TableSchema tableSchema)
{
if (tableSchema.HasPrimaryKey)
{
var method = GetMethodFromColumns(entity, tableSchema.PrimaryKey.MemberColumns);
if (method != null)
{
method.IsKey = true;
method.SourceName = tableSchema.PrimaryKey.FullName;
if (!entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
entity.Methods.Add(method);
}
}
GetIndexMethods(entity, tableSchema);
GetForeignKeyMethods(entity, tableSchema);
entity.Methods.IsProcessed = true;
}
private static void GetForeignKeyMethods(Entity entity, TableSchema table)
{
var columns = new List<ColumnSchema>();
foreach (ColumnSchema column in table.ForeignKeyColumns)
{
columns.Add(column);
Method method = GetMethodFromColumns(entity, columns);
if (method != null && !entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
entity.Methods.Add(method);
columns.Clear();
}
}
private static void GetIndexMethods(Entity entity, TableSchema table)
{
foreach (IndexSchema index in table.Indexes)
{
Method method = GetMethodFromColumns(entity, index.MemberColumns);
if (method == null)
continue;
method.SourceName = index.FullName;
method.IsUnique = index.IsUnique;
method.IsIndex = true;
if (!entity.Methods.Any(m => m.NameSuffix == method.NameSuffix))
entity.Methods.Add(method);
}
}
private static Method GetMethodFromColumns(Entity entity, IEnumerable<ColumnSchema> columns)
{
var method = new Method();
string methodName = string.Empty;
foreach (var column in columns)
{
var property = entity.Properties.ByColumn(column.Name);
if (property == null)
continue;
method.Properties.Add(property);
methodName += property.PropertyName;
}
if (method.Properties.Count == 0)
return null;
method.NameSuffix = methodName;
return method;
}
private static List<string> GetKeyMembers(Entity entity, IEnumerable<MemberColumnSchema> members, string name, out bool isRequired)
{
var keyMembers = new List<string>();
isRequired = false;
foreach (var member in members)
{
var property = entity.Properties.ByColumn(member.Name);
if (property == null)
throw new InvalidOperationException(string.Format(
"Could not find column {0} for relationship {1}.",
member.Name,
name));
if (!isRequired)
isRequired = property.IsRequired;
keyMembers.Add(property.PropertyName);
}
return keyMembers;
}
private static string GetMemberPrefix(Relationship relationship, string primaryClass, string foreignClass)
{
string thisKey = relationship.ThisProperties.FirstOrDefault() ?? string.Empty;
string otherKey = relationship.OtherProperties.FirstOrDefault() ?? string.Empty;
bool isSameName = thisKey.Equals(otherKey, StringComparison.OrdinalIgnoreCase);
isSameName = (isSameName || thisKey.Equals(primaryClass + otherKey, StringComparison.OrdinalIgnoreCase));
string prefix = string.Empty;
if (isSameName)
return prefix;
prefix = thisKey.Replace(otherKey, "");
prefix = prefix.Replace(primaryClass, "");
prefix = prefix.Replace(foreignClass, "");
prefix = Regex.Replace(prefix, @"(_ID|_id|_Id|\.ID|\.id|\.Id|ID|Id)$", "");
prefix = Regex.Replace(prefix, @"^\d", "");
return prefix;
}
private static bool IsOneToOne(TableKeySchema tableKeySchema, Relationship foreignRelationship)
{
bool isFkeyPkey = tableKeySchema.ForeignKeyTable.HasPrimaryKey
&& tableKeySchema.ForeignKeyTable.PrimaryKey != null
&& tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Count == 1
&& tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Contains(
foreignRelationship.ThisProperties.FirstOrDefault());
if (isFkeyPkey)
return true;
// if f.key is unique
return tableKeySchema.ForeignKeyMemberColumns.All(column => column.IsUnique);
}
private static bool IsManyToMany(TableSchema tableSchema)
{
// 1) Table must have Two ForeignKeys.
// 2) All columns must be either...
// a) Member of a Foreign Key.
// b) DbGenerated
if (tableSchema.Columns.Count < 2)
return false;
if (tableSchema.ForeignKeyColumns.Count != 2)
return false;
// all columns are fkeys
if (tableSchema.Columns.Count == 2 &&
tableSchema.ForeignKeyColumns.Count == 2)
return true;
// check all non fkey columns to make sure db gen'd
return tableSchema.NonForeignKeyColumns.All(c =>
IsDbGenerated(c) || HasDefaultValue(c));
}
#region Name Helpers
private string ToClassName(string name)
{
name = Settings.EntityName(name);
string legalName = ToLegalName(name);
return legalName;
}
private string ToPropertyName(string className, string name)
{
string propertyName = ToLegalName(name);
if (className.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
propertyName += "Member";
return propertyName;
}
private string ToLegalName(string name)
{
string legalName = Settings.CleanName(name);
legalName = StringUtil.ToPascalCase(legalName);
return legalName;
}
#endregion
#region Column Flag Helpers
private static bool IsCascadeDelete(SchemaObjectBase column)
{
bool cascadeDelete = false;
string value;
try
{
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.CascadeDelete))
{
value = column.ExtendedProperties[ExtendedPropertyNames.CascadeDelete].Value.ToString();
bool.TryParse(value, out cascadeDelete);
}
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
}
return cascadeDelete;
}
private static bool IsRowVersion(DataObjectBase column)
{
bool isTimeStamp = column.NativeType.Equals(
"timestamp", StringComparison.OrdinalIgnoreCase);
bool isRowVersion = column.NativeType.Equals(
"rowversion", StringComparison.OrdinalIgnoreCase);
return (isTimeStamp || isRowVersion);
}
private static bool IsDbGenerated(DataObjectBase column)
{
if (IsRowVersion(column))
return true;
if (IsIdentity(column))
return true;
bool isComputed = false;
string value;
try
{
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.IsComputed))
{
value = column.ExtendedProperties[ExtendedPropertyNames.IsComputed].Value.ToString();
bool.TryParse(value, out isComputed);
}
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
}
return isComputed;
}
private static bool IsIdentity(DataObjectBase column)
{
string temp;
bool isIdentity = false;
try
{
if (column.ExtendedProperties.Contains(ExtendedPropertyNames.IsIdentity))
{
temp = column.ExtendedProperties[ExtendedPropertyNames.IsIdentity].Value.ToString();
bool.TryParse(temp, out isIdentity);
}
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
}
return isIdentity;
}
private static bool HasDefaultValue(DataObjectBase column)
{
try
{
if (!column.ExtendedProperties.Contains(ExtendedPropertyNames.DefaultValue))
return false;
string value = column.ExtendedProperties[ExtendedPropertyNames.DefaultValue].Value.ToString();
return !string.IsNullOrEmpty(value);
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
}
return false;
}
#endregion
}
}

View File

@ -0,0 +1,370 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Xml.Serialization;
namespace SchemaMapper
{
#region Base
public enum Cardinality
{
ZeroOrOne,
One,
Many
}
public class EntityBase
{
[XmlIgnore]
public bool IsProcessed { get; set; }
}
#endregion
#region Model
[DebuggerDisplay("Context: {ContextName}, Database: {DatabaseName}")]
public class EntityContext : EntityBase
{
public EntityContext()
{
Entities = new EntityCollection();
}
public string ClassName { get; set; }
public string DatabaseName { get; set; }
public EntityCollection Entities { get; set; }
public void RenameEntity(string originalName, string newName)
{
if (originalName == newName)
return;
Debug.WriteLine("Rename Entity '{0}' to '{1}'.", originalName, newName);
foreach (var entity in Entities)
{
if (entity.ClassName == originalName)
entity.ClassName = newName;
foreach (var relationship in entity.Relationships)
{
if (relationship.ThisEntity == originalName)
relationship.ThisEntity = newName;
if (relationship.OtherEntity == originalName)
relationship.OtherEntity = newName;
}
}
}
public void RenameProperty(string entityName, string originalName, string newName)
{
if (originalName == newName)
return;
Debug.WriteLine("Rename Property '{0}' to '{1}' in Entity '{2}'.", originalName, newName, entityName);
foreach (var entity in Entities)
{
if (entity.ClassName == entityName)
{
var property = entity.Properties.ByProperty(originalName);
if (property != null)
property.PropertyName = newName;
}
foreach (var relationship in entity.Relationships)
{
if (relationship.ThisEntity == entityName)
for (int i = 0; i < relationship.ThisProperties.Count; i++)
if (relationship.ThisProperties[i] == originalName)
relationship.ThisProperties[i] = newName;
if (relationship.OtherEntity == entityName)
for (int i = 0; i < relationship.OtherProperties.Count; i++)
if (relationship.OtherProperties[i] == originalName)
relationship.OtherProperties[i] = newName;
}
}
}
}
[DebuggerDisplay("Class: {ClassName}, Table: {FullName}, Context: {ContextName}")]
public class Entity : EntityBase
{
public Entity()
{
Properties = new PropertyCollection();
Relationships = new RelationshipCollection();
Methods = new MethodCollection();
}
public string ContextName { get; set; }
public string ClassName { get; set; }
public string MappingName { get; set; }
public string Description{ get;set;}
public string TableSchema { get; set; }
public string TableName { get; set; }
public string FullName { get; set; }
public PropertyCollection Properties { get; set; }
public RelationshipCollection Relationships { get; set; }
public MethodCollection Methods { get; set; }
}
[DebuggerDisplay("Property: {PropertyName}, Column: {ColumnName}, Type: {NativeType}")]
public class Property : EntityBase
{
public string PropertyName { get; set; }
public string ColumnName { get; set; }
public string Description { get; set; }
public DbType DataType { get; set; }
public string NativeType { get; set; }
[XmlIgnore]
public Type SystemType { get; set; }
public int? Order { get; set; }
public bool OrderSpecified
{
get { return Order.HasValue; }
}
public bool? IsNullable { get; set; }
public bool IsNullableSpecified
{
get { return IsNullable.HasValue; }
}
public bool IsRequired
{
get { return IsNullable == false; }
set { IsNullable = !value; }
}
public bool IsOptional
{
get { return IsNullable == true; }
set { IsNullable = value; }
}
public bool? IsPrimaryKey { get; set; }
public bool IsPrimaryKeySpecified
{
get { return IsPrimaryKey.HasValue; }
}
public bool? IsForeignKey { get; set; }
public bool IsForeignKeySpecified
{
get { return IsForeignKey.HasValue; }
}
public bool? IsAutoGenerated { get; set; }
public bool IsAutoGeneratedSpecified
{
get { return IsAutoGenerated.HasValue; }
}
public bool? IsReadOnly { get; set; }
public bool IsReadOnlySpecified
{
get { return IsReadOnly.HasValue; }
}
public bool? IsRowVersion { get; set; }
public bool IsRowVersionSpecified
{
get { return IsRowVersion.HasValue; }
}
public bool? IsIdentity { get; set; }
public bool IsIdentitySpecified
{
get { return IsIdentity.HasValue; }
}
public bool? IsUnique { get; set; }
public bool IsUniqueSpecified
{
get { return IsUnique.HasValue; }
}
public bool? IsUnicode { get; set; }
public bool IsUnicodeSpecified
{
get { return IsUnicode.HasValue; }
}
public bool? IsFixedLength { get; set; }
public bool IsFixedLengthSpecified
{
get { return IsFixedLength.HasValue; }
}
public int? MaxLength { get; set; }
public bool MaxLengthSpecified
{
get { return MaxLength.HasValue; }
}
public byte? Precision { get; set; }
public bool PrecisionSpecified
{
get { return Precision.HasValue; }
}
public int? Scale { get; set; }
public bool ScaleSpecified
{
get { return Scale.HasValue; }
}
}
[DebuggerDisplay("Other: {OtherEntity}, Property: {OtherPropertyName}, Relationship: {RelationshipName}")]
public class Relationship : EntityBase
{
public Relationship()
{
OtherProperties = new List<string>();
ThisProperties = new List<string>();
}
public string RelationshipName { get; set; }
public string ThisEntity { get; set; }
public string ThisPropertyName { get; set; }
public Cardinality ThisCardinality { get; set; }
public List<string> ThisProperties { get; set; }
public string OtherEntity { get; set; }
public string OtherPropertyName { get; set; }
public Cardinality OtherCardinality { get; set; }
public List<string> OtherProperties { get; set; }
public bool? CascadeDelete { get; set; }
public bool IsForeignKey { get; set; }
public bool IsMapped { get; set; }
public bool IsManyToMany
{
get
{
return ThisCardinality == Cardinality.Many
&& OtherCardinality == Cardinality.Many;
}
}
public bool IsOneToOne
{
get
{
return ThisCardinality != Cardinality.Many
&& OtherCardinality != Cardinality.Many;
}
}
public string JoinTable { get; set; }
public string JoinSchema { get; set; }
public List<string> JoinThisColumn { get; set; }
public List<string> JoinOtherColumn { get; set; }
}
[DebuggerDisplay("Suffix: {NameSuffix}, IsKey: {IsKey}, IsUnique: {IsUnique}")]
public class Method : EntityBase
{
public Method()
{
Properties = new List<Property>();
}
public string NameSuffix { get; set; }
public string SourceName { get; set; }
public bool IsKey { get; set; }
public bool IsUnique { get; set; }
public bool IsIndex { get; set; }
public List<Property> Properties { get; set; }
}
#endregion
#region Collections
public class EntityCollection
: ObservableCollection<Entity>
{
public bool IsProcessed { get; set; }
public Entity ByTable(string fullName)
{
return this.FirstOrDefault(x => x.FullName == fullName);
}
public Entity ByTable(string tableName, string tableSchema)
{
return this.FirstOrDefault(x => x.TableName == tableName && x.TableSchema == tableSchema);
}
public Entity ByClass(string className)
{
return this.FirstOrDefault(x => x.ClassName == className);
}
public Entity ByContext(string contextName)
{
return this.FirstOrDefault(x => x.ContextName == contextName);
}
}
public class PropertyCollection
: ObservableCollection<Property>
{
public bool IsProcessed { get; set; }
public IEnumerable<Property> PrimaryKeys
{
get { return this.Where(p => p.IsPrimaryKey == true); }
}
public IEnumerable<Property> ForeignKeys
{
get { return this.Where(p => p.IsForeignKey == true); }
}
public Property ByColumn(string columnName)
{
return this.FirstOrDefault(x => x.ColumnName == columnName);
}
public Property ByProperty(string propertyName)
{
return this.FirstOrDefault(x => x.PropertyName == propertyName);
}
}
public class RelationshipCollection
: ObservableCollection<Relationship>
{
public bool IsProcessed { get; set; }
public Relationship ByName(string name)
{
return this.FirstOrDefault(x => x.RelationshipName == name);
}
public Relationship ByProperty(string propertyName)
{
return this.FirstOrDefault(x => x.ThisPropertyName == propertyName);
}
public Relationship ByOther(string name)
{
return this.FirstOrDefault(x => x.OtherEntity == name);
}
}
public class MethodCollection
: ObservableCollection<Method>
{
public bool IsProcessed { get; set; }
}
#endregion
}

View File

@ -0,0 +1,639 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory.CSharp;
namespace SchemaMapper
{
#region Mapping Parser
[DebuggerDisplay("Table: {TableName}, Entity: {EntityClass}, Mapping: {MappingClass}")]
public class ParsedEntity
{
public ParsedEntity()
{
Properties = new List<ParsedProperty>();
Relationships = new List<ParsedRelationship>();
}
public string EntityClass { get; set; }
public string MappingClass { get; set; }
public string TableName { get; set; }
public string TableSchema { get; set; }
public List<ParsedProperty> Properties { get; private set; }
public List<ParsedRelationship> Relationships { get; private set; }
}
[DebuggerDisplay("Column: {ColumnName}, Property: {PropertyName}")]
public class ParsedProperty
{
public string ColumnName { get; set; }
public string PropertyName { get; set; }
}
[DebuggerDisplay("This: {ThisPropertyName}, Other: {OtherPropertyName}")]
public class ParsedRelationship
{
public ParsedRelationship()
{
ThisProperties = new List<string>();
JoinThisColumn = new List<string>();
JoinOtherColumn = new List<string>();
}
public string ThisPropertyName { get; set; }
public List<string> ThisProperties { get; private set; }
public string OtherPropertyName { get; set; }
public string JoinTable { get; set; }
public string JoinSchema { get; set; }
public List<string> JoinThisColumn { get; private set; }
public List<string> JoinOtherColumn { get; private set; }
}
public class MappingVisitor : DepthFirstAstVisitor<object, object>
{
public MappingVisitor()
{
MappingBaseType = "EntityTypeConfiguration";
}
public string MappingBaseType { get; set; }
public ParsedEntity ParsedEntity { get; set; }
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
var baseType = typeDeclaration.BaseTypes.OfType<MemberType>().FirstOrDefault();
if (baseType == null || baseType.MemberName != MappingBaseType)
return base.VisitTypeDeclaration(typeDeclaration, data);
var entity = baseType.TypeArguments.OfType<MemberType>().FirstOrDefault();
if (entity == null)
return base.VisitTypeDeclaration(typeDeclaration, data);
if (ParsedEntity == null)
ParsedEntity = new ParsedEntity();
ParsedEntity.EntityClass = entity.MemberName;
ParsedEntity.MappingClass = typeDeclaration.Name;
return base.VisitTypeDeclaration(typeDeclaration, ParsedEntity);
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
if (data == null)
return base.VisitInvocationExpression(invocationExpression, null);
// visit all the methods
var identifier = invocationExpression.Target.Children.OfType<Identifier>().FirstOrDefault();
string methodName = identifier == null ? string.Empty : identifier.Name;
// the different types of incoming data, helps us know what we're parsing
var parsedEntity = data as ParsedEntity;
var parsedProperty = data as ParsedProperty;
var parsedRelationship = data as ParsedRelationship;
switch (methodName)
{
case "ToTable":
var tableNameExpression = invocationExpression.Arguments
.OfType<PrimitiveExpression>()
.ToArray();
string tableName = null;
string tableSchema = null;
if (tableNameExpression.Length >= 1)
tableName = tableNameExpression[0].Value.ToString();
if (tableNameExpression.Length >= 2)
tableSchema = tableNameExpression[1].Value.ToString();
// ToTable is either Entity -> Table map or Many to Many map
if (parsedEntity != null)
{
// when data is ParsedEntity, entity map
parsedEntity.TableName = tableName;
parsedEntity.TableSchema = tableSchema;
}
else if (parsedRelationship != null)
{
// when data is ParsedRelationship, many to many map
parsedRelationship.JoinTable = tableName;
parsedRelationship.JoinSchema = tableSchema;
}
break;
case "HasColumnName":
var columnNameExpression = invocationExpression.Arguments
.OfType<PrimitiveExpression>()
.FirstOrDefault();
if (columnNameExpression == null)
break;
// property to column map start.
string columnName = columnNameExpression.Value.ToString();
var property = new ParsedProperty { ColumnName = columnName };
ParsedEntity.Properties.Add(property);
//only have column info at this point. pass data to get property name.
return base.VisitInvocationExpression(invocationExpression, property);
case "Property":
var propertyExpression = invocationExpression.Arguments
.OfType<LambdaExpression>()
.FirstOrDefault();
if (parsedProperty == null || propertyExpression == null)
break;
// ParsedProperty is passed in as data from HasColumnName, add property name
var propertyBodyExpression = propertyExpression.Body as MemberReferenceExpression;
if (propertyBodyExpression != null)
parsedProperty.PropertyName = propertyBodyExpression.MemberName;
break;
case "Map":
// start a new Many to Many relationship
var mapRelation = new ParsedRelationship();
ParsedEntity.Relationships.Add(mapRelation);
// pass to child nodes to fill in data
return base.VisitInvocationExpression(invocationExpression, mapRelation);
case "HasForeignKey":
var foreignExpression = invocationExpression.Arguments
.OfType<LambdaExpression>()
.FirstOrDefault();
if (foreignExpression == null)
break;
// when only 1 fkey, body will be member ref
if (foreignExpression.Body is MemberReferenceExpression)
{
var foreignBodyExpression = foreignExpression.Body as MemberReferenceExpression;
// start a new relationship
var foreignRelation = new ParsedRelationship();
ParsedEntity.Relationships.Add(foreignRelation);
foreignRelation.ThisProperties.Add(foreignBodyExpression.MemberName);
// pass as data for child nodes to fill in data
return base.VisitInvocationExpression(invocationExpression, foreignRelation);
}
// when more then 1 fkey, body will be an anonymous type
if (foreignExpression.Body is AnonymousTypeCreateExpression)
{
var foreignBodyExpression = foreignExpression.Body as AnonymousTypeCreateExpression;
var foreignRelation = new ParsedRelationship();
ParsedEntity.Relationships.Add(foreignRelation);
var properties = foreignBodyExpression.Children
.OfType<MemberReferenceExpression>()
.Select(m => m.MemberName);
foreignRelation.ThisProperties.AddRange(properties);
return base.VisitInvocationExpression(invocationExpression, foreignRelation);
}
break;
case "HasMany":
var hasManyExpression = invocationExpression.Arguments
.OfType<LambdaExpression>()
.FirstOrDefault();
if (parsedRelationship == null || hasManyExpression == null)
break;
// filling existing relationship data
var hasManyBodyExpression = hasManyExpression.Body as MemberReferenceExpression;
if (hasManyBodyExpression != null)
parsedRelationship.ThisPropertyName = hasManyBodyExpression.MemberName;
break;
case "WithMany":
var withManyExpression = invocationExpression.Arguments
.OfType<LambdaExpression>()
.FirstOrDefault();
if (parsedRelationship == null || withManyExpression == null)
break;
// filling existing relationship data
var withManyBodyExpression = withManyExpression.Body as MemberReferenceExpression;
if (withManyBodyExpression != null)
parsedRelationship.OtherPropertyName = withManyBodyExpression.MemberName;
break;
case "HasRequired":
case "HasOptional":
var hasExpression = invocationExpression.Arguments
.OfType<LambdaExpression>()
.FirstOrDefault();
if (parsedRelationship == null || hasExpression == null)
break;
// filling existing relationship data
var hasBodyExpression = hasExpression.Body as MemberReferenceExpression;
if (hasBodyExpression != null)
parsedRelationship.ThisPropertyName = hasBodyExpression.MemberName;
break;
case "MapLeftKey":
if (parsedRelationship == null)
break;
var leftKeyExpression = invocationExpression.Arguments
.OfType<PrimitiveExpression>()
.Select(e => e.Value.ToString());
parsedRelationship.JoinThisColumn.AddRange(leftKeyExpression);
break;
case "MapRightKey":
if (parsedRelationship == null)
break;
var rightKeyExpression = invocationExpression.Arguments
.OfType<PrimitiveExpression>()
.Select(e => e.Value.ToString());
parsedRelationship.JoinOtherColumn.AddRange(rightKeyExpression);
break;
}
return base.VisitInvocationExpression(invocationExpression, data);
}
}
public static class MappingParser
{
public static ParsedEntity Parse(string mappingFile)
{
if (string.IsNullOrEmpty(mappingFile) || !File.Exists(mappingFile))
return null;
var parser = new CSharpParser();
CompilationUnit compilationUnit;
using (var stream = File.OpenText(mappingFile))
compilationUnit = parser.Parse(stream, mappingFile);
var visitor = new MappingVisitor();
visitor.VisitCompilationUnit(compilationUnit, null);
var parsedEntity = visitor.ParsedEntity;
if (parsedEntity != null)
Debug.WriteLine("Parsed Mapping File: '{0}'; Properties: {1}; Relationships: {2}",
Path.GetFileName(mappingFile),
parsedEntity.Properties.Count,
parsedEntity.Relationships.Count);
return parsedEntity;
}
}
#endregion
#region Context Parser
[DebuggerDisplay("Context: {ContextClass}")]
public class ParsedContext
{
public ParsedContext()
{
Properties = new List<ParsedEntitySet>();
}
public string ContextClass { get; set; }
public List<ParsedEntitySet> Properties { get; private set; }
}
[DebuggerDisplay("Entity: {EntityClass}, Property: {ContextProperty}")]
public class ParsedEntitySet
{
public string EntityClass { get; set; }
public string ContextProperty { get; set; }
}
public class ContextVisitor : DepthFirstAstVisitor<object, object>
{
public ContextVisitor()
{
ContextBaseType = "DbContext";
DataSetType = "DbSet";
}
public string ContextBaseType { get; set; }
public string DataSetType { get; set; }
public ParsedContext ParsedContext { get; set; }
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
var baseType = typeDeclaration.BaseTypes
.OfType<MemberType>()
.FirstOrDefault();
// warning: if inherited from custom base type, this will break
// anyway to improve this?
if (baseType == null || baseType.MemberName != ContextBaseType)
return base.VisitTypeDeclaration(typeDeclaration, data);
if (ParsedContext == null)
ParsedContext = new ParsedContext();
ParsedContext.ContextClass = typeDeclaration.Name;
return base.VisitTypeDeclaration(typeDeclaration, ParsedContext);
}
public override object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
{
if (data == null)
return base.VisitPropertyDeclaration(propertyDeclaration, null);
// look for property to return generic DbSet type
var memberType = propertyDeclaration.ReturnType as MemberType;
if (memberType == null || memberType.MemberName != DataSetType)
return base.VisitPropertyDeclaration(propertyDeclaration, data);
// get the first generic type
var entityType = memberType.TypeArguments
.OfType<MemberType>()
.FirstOrDefault();
if (entityType == null)
return base.VisitPropertyDeclaration(propertyDeclaration, data);
var entitySet = new ParsedEntitySet
{
EntityClass = entityType.MemberName,
ContextProperty = propertyDeclaration.Name
};
ParsedContext.Properties.Add(entitySet);
return base.VisitPropertyDeclaration(propertyDeclaration, data);
}
}
public static class ContextParser
{
public static ParsedContext Parse(string contextFile)
{
if (string.IsNullOrEmpty(contextFile) || !File.Exists(contextFile))
return null;
var parser = new CSharpParser();
CompilationUnit compilationUnit;
using (var stream = File.OpenText(contextFile))
compilationUnit = parser.Parse(stream, contextFile);
var visitor = new ContextVisitor();
visitor.VisitCompilationUnit(compilationUnit, null);
var parsedContext = visitor.ParsedContext;
if (parsedContext != null)
Debug.WriteLine("Parsed Context File: '{0}'; Entities: {1}",
Path.GetFileName(contextFile),
parsedContext.Properties.Count);
return parsedContext;
}
}
#endregion
public static class Synchronizer
{
public static bool UpdateFromSource(EntityContext generatedContext, string contextDirectory, string mappingDirectory)
{
if (generatedContext == null)
return false;
// make sure to update the entities before the context
UpdateFromMapping(generatedContext, mappingDirectory);
UpdateFromContext(generatedContext, contextDirectory);
return true;
}
private static void UpdateFromContext(EntityContext generatedContext, string contextDirectory)
{
if (generatedContext == null
|| contextDirectory == null
|| !Directory.Exists(contextDirectory))
return;
// parse context
ParsedContext parsedContext = null;
var files = Directory.EnumerateFiles(contextDirectory, "*.Generated.cs").GetEnumerator();
while (files.MoveNext() && parsedContext == null)
parsedContext = ContextParser.Parse(files.Current);
if (parsedContext == null)
return;
if (generatedContext.ClassName != parsedContext.ContextClass)
{
Debug.WriteLine("Rename Context Class'{0}' to '{1}'.",
generatedContext.ClassName,
parsedContext.ContextClass);
generatedContext.ClassName = parsedContext.ContextClass;
}
foreach (var parsedProperty in parsedContext.Properties)
{
var entity = generatedContext.Entities.ByClass(parsedProperty.EntityClass);
if (entity == null)
continue;
if (entity.ContextName == parsedProperty.ContextProperty)
continue;
Debug.WriteLine("Rename Context Property'{0}' to '{1}'.",
entity.ContextName,
parsedProperty.ContextProperty);
entity.ContextName = parsedProperty.ContextProperty;
}
}
private static void UpdateFromMapping(EntityContext generatedContext, string mappingDirectory)
{
if (generatedContext == null
|| mappingDirectory == null
|| !Directory.Exists(mappingDirectory))
return;
// parse all mapping files
var mappingFiles = Directory.EnumerateFiles(mappingDirectory, "*.Generated.cs");
var parsedEntities = mappingFiles
.Select(MappingParser.Parse)
.Where(parsedEntity => parsedEntity != null)
.ToList();
var relationshipQueue = new List<Tuple<Entity, ParsedEntity>>();
// update all entity and property names first because relationships are linked by property names
foreach (var parsedEntity in parsedEntities)
{
// find entity by table name to support renaming entity
var entity = generatedContext.Entities
.ByTable(parsedEntity.TableName, parsedEntity.TableSchema);
if (entity == null)
continue;
// sync names
if (entity.MappingName != parsedEntity.MappingClass)
{
Debug.WriteLine("Rename Mapping Class'{0}' to '{1}'.",
entity.MappingName,
parsedEntity.MappingClass);
entity.MappingName = parsedEntity.MappingClass;
}
// use rename api to make sure all instances are renamed
generatedContext.RenameEntity(entity.ClassName, parsedEntity.EntityClass);
// sync properties
foreach (var parsedProperty in parsedEntity.Properties)
{
// find property by column name to support property name rename
var property = entity.Properties.ByColumn(parsedProperty.ColumnName);
if (property == null)
continue;
// use rename api to make sure all instances are renamed
generatedContext.RenameProperty(
entity.ClassName,
property.PropertyName,
parsedProperty.PropertyName);
}
// save relationship for later processing
var item = new Tuple<Entity, ParsedEntity>(entity, parsedEntity);
relationshipQueue.Add(item);
}
// update relationships last
foreach (var tuple in relationshipQueue)
UpdateRelationships(generatedContext, tuple.Item1, tuple.Item2);
}
private static void UpdateRelationships(EntityContext generatedContext, Entity entity, ParsedEntity parsedEntity)
{
// sync relationships
foreach (var parsedRelationship in parsedEntity.Relationships.Where(r => r.JoinTable == null))
{
var parsedProperties = parsedRelationship.ThisProperties;
var relationship = entity.Relationships
.Where(r => !r.IsManyToMany)
.FirstOrDefault(r => r.ThisProperties.Except(parsedProperties).Count() == 0);
if (relationship == null)
continue;
bool isThisSame = relationship.ThisPropertyName == parsedRelationship.ThisPropertyName;
bool isOtherSame = relationship.OtherPropertyName == parsedRelationship.OtherPropertyName;
if (isThisSame && isOtherSame)
continue;
if (!isThisSame)
{
Debug.WriteLine("Rename Relationship Property '{0}.{1}' to '{0}.{2}'.",
relationship.ThisEntity,
relationship.ThisPropertyName,
parsedRelationship.ThisPropertyName);
relationship.ThisPropertyName = parsedRelationship.ThisPropertyName;
}
if (!isOtherSame)
{
Debug.WriteLine("Rename Relationship Property '{0}.{1}' to '{0}.{2}'.",
relationship.OtherEntity,
relationship.OtherPropertyName,
parsedRelationship.OtherPropertyName);
relationship.OtherPropertyName = parsedRelationship.OtherPropertyName;
}
// sync other relationship
var otherEntity = generatedContext.Entities.ByClass(relationship.OtherEntity);
if (otherEntity == null)
continue;
var otherRelationship = otherEntity.Relationships.ByName(relationship.RelationshipName);
if (otherRelationship == null)
continue;
otherRelationship.ThisPropertyName = relationship.OtherPropertyName;
otherRelationship.OtherPropertyName = relationship.ThisPropertyName;
}
// sync many to many
foreach (var parsedRelationship in parsedEntity.Relationships.Where(r => r.JoinTable != null))
{
var joinThisColumn = parsedRelationship.JoinThisColumn;
var joinOtherColumn = parsedRelationship.JoinOtherColumn;
var relationship = entity.Relationships
.Where(r => r.IsManyToMany)
.FirstOrDefault(r =>
r.JoinThisColumn.Except(joinThisColumn).Count() == 0 &&
r.JoinOtherColumn.Except(joinOtherColumn).Count() == 0 &&
r.JoinTable == parsedRelationship.JoinTable &&
r.JoinSchema == parsedRelationship.JoinSchema);
if (relationship == null)
continue;
bool isThisSame = relationship.ThisPropertyName == parsedRelationship.ThisPropertyName;
bool isOtherSame = relationship.OtherPropertyName == parsedRelationship.OtherPropertyName;
if (isThisSame && isOtherSame)
continue;
if (!isThisSame)
{
Debug.WriteLine("Rename Relationship Property '{0}.{1}' to '{0}.{2}'.",
relationship.ThisEntity,
relationship.ThisPropertyName,
parsedRelationship.ThisPropertyName);
relationship.ThisPropertyName = parsedRelationship.ThisPropertyName;
}
if (!isOtherSame)
{
Debug.WriteLine("Rename Relationship Property '{0}.{1}' to '{0}.{2}'.",
relationship.OtherEntity,
relationship.OtherPropertyName,
parsedRelationship.OtherPropertyName);
relationship.OtherPropertyName = parsedRelationship.OtherPropertyName;
}
// sync other relationship
var otherEntity = generatedContext.Entities.ByClass(relationship.OtherEntity);
if (otherEntity == null)
continue;
var otherRelationship = otherEntity.Relationships.ByName(relationship.RelationshipName);
if (otherRelationship == null)
continue;
otherRelationship.ThisPropertyName = relationship.OtherPropertyName;
otherRelationship.OtherPropertyName = relationship.ThisPropertyName;
}
}
}
}

View File

@ -0,0 +1,105 @@
<%--
Name: Database Table Properties
Author: yubaolee
Description: Create a list of properties from a database table
--%>
<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="False" Description="控制器" %>
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
using System;
using System.Collections.Generic;
using System.Linq;
using Infrastructure;
using Microsoft.AspNetCore.Mvc;
using OpenAuth.App;
using OpenAuth.App.Interface;
using OpenAuth.App.Request;
using OpenAuth.Repository.Domain;
namespace OpenAuth.Mvc.Controllers
{
public class <%=ModuleName%>sController : BaseController
{
private readonly <%=ModuleName%>App _app;
public <%=ModuleName%>sController(<%=ModuleName%>App app, IAuth auth) : base(auth)
{
_app = app;
}
//主页
public ActionResult Index()
{
return View();
}
/// <summary>
/// MVC界面添加
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
[HttpPost]
public string Add(AddOrUpdate<%=ModuleName%>Req obj)
{
try
{
_app.Add(obj);
}
catch (Exception ex)
{
Result.Code = 500;
Result.Message = ex.Message;
}
return JsonHelper.Instance.Serialize(Result);
}
/// <summary>
/// MVC界面修改
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
[HttpPost]
public string Update(AddOrUpdate<%=ModuleName%>Req obj)
{
try
{
_app.Update(obj);
}
catch (Exception ex)
{
Result.Code = 500;
Result.Message = ex.Message;
}
return JsonHelper.Instance.Serialize(Result);
}
/// <summary>
/// 加载列表
/// </summary>
public string Load([FromQuery]Query<%=ModuleName%>ListReq request)
{
return JsonHelper.Instance.Serialize(_app.Load(request));
}
[HttpPost]
public string Delete(string[] ids)
{
try
{
_app.Delete(ids);
}
catch (Exception e)
{
Result.Code = 500;
Result.Message = e.Message;
}
return JsonHelper.Instance.Serialize(Result);
}
}
}

View File

@ -0,0 +1,98 @@
<%--
Name: 列表页面
Author: yubaolee
Description: 列表页面
--%>
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Debug="False" Encoding="utf-8" Description="添加模块" %>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context"
Description="连接的数据库" %>
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Assembly Src="Util.cs" %>
<%@ Import Namespace="Util" %>
@section header
{
<link rel="stylesheet" href="/css/treetable.css" />
}
<blockquote class="layui-elem-quote news_search toolList" id="menus">
</blockquote>
<div class="layui-card">
<table class="layui-table" id="mainList"
lay-data="{height: 'full-80', page:true, id:'mainList'}"
lay-filter="list" lay-size="sm">
</table>
<script type="text/html" id="Disable">
{{# if(d.Disable){ }}
<span class="layui-badge">已禁用</span>
{{# } else{}}
<span class="layui-badge layui-bg-green">正常</span>
{{# } }}
</script>
</div>
<!--添加/编辑窗口-->
<div id="divEdit" style="display: none">
<form class="layui-form" action="" id="formEdit">
<% foreach (ColumnSchema column in this.SourceTable.Columns) {
if(column.IsPrimaryKeyMember){%>
<input type="hidden" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" />
<%}else if(CSharpAlias[column.SystemType.FullName] == "bool") {%>
<div class="layui-form-item">
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
<div class="layui-input-block">
<input type="checkbox" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" lay-skin="switch" value="1">
</div>
</div>
<%}else if(CSharpAlias[column.SystemType.FullName] == "int" ) {%>
<div class="layui-form-item">
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
<div class="layui-input-block">
<input type="radio" name="<%=column.Name%>" value="1" title="value1" checked>
<input type="radio" name="<%=column.Name%>" value="0" title="value2">
</div>
</div>
<%} else {%>
<div class="layui-form-item">
<label class="layui-form-label"><%=Tools.GetDescription(column)%></label>
<div class="layui-input-block">
<input type="text" name="<%=column.Name%>" v-model="tmp.<%=column.Name%>" required lay-verify="required"
placeholder="<%=Tools.GetDescription(column)%>" autocomplete="off" class="layui-input">
</div>
</div>
<%} %>
<%} %>
<%if(Tools.NeedCascade(SourceTable)){ %>
<div class="layui-form-item">
<label class="layui-form-label">所属部门</label>
<div class="layui-input-block">
<input id="Organizations" name="Organizations" v-model="Organizations" required lay-verify="required" class="layui-input" />
<input id="OrganizationIds" name="OrganizationIds" v-model="OrganizationIds" required lay-verify="required" type="hidden" />
<div id="menuContent" class="menuContent" style="display: none;">
<ul id="org" class="ztree"></ul>
</div>
</div>
</div>
<%} %>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="formSubmit">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
<script type="text/javascript" src="/layui/layui.js"></script>
<script type="text/javascript" src="/userJs/<%=ModuleName.ToLower()%>s.js"></script>

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using CodeSmith.Engine;
using SchemaExplorer;
namespace Util{
public class Tools{
public static String GetDescription(ColumnSchema column) { //得到字段的描述
if(string.IsNullOrEmpty(column.Description))
return column.Name;
else
return column.Description;
}
public static bool NeedCascade(TableSchema SourceTable){ //判断表中是否需要下拉选择树
return SourceTable.Columns.Contains("ParentId")
|| SourceTable.Columns.Contains("CascadeId") ;
}
public static string CreateBlank(int level){
if(level == 1){
return " ";
}
else{
var twoblanks = " ";
for (int i = level-1; i > 1; i--)
{
twoblanks +=twoblanks;
}
return CreateBlank(1) + twoblanks;
}
}
}
}

View File

@ -0,0 +1,186 @@
<%--
Name: 主JS界面
Author: yubaolee
--%>
<%@ CodeTemplate Language="C#" TargetLanguage="C#" Debug="False" Encoding="utf-8" Description="添加模块" %>
<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Assembly Src="Util.cs" %>
<%@ Import Namespace="Util" %>
layui.config({
base: "/js/"
}).use(['form', 'vue', 'ztree', 'layer', 'jquery', 'table', 'droptree', 'openauth', 'utils'], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.jquery;
var table = layui.table;
var openauth = layui.openauth;
var toplayer = (top == undefined || top.layer === undefined) ? layer : top.layer; //顶层的LAYER
$("#menus").loadMenus("<%=ModuleName%>");
//加载表头
$.getJSON('/<%=ModuleName%>s/Load',
{ page: 1, limit: 1 },
function (data) {
var columns = data.columnFields.filter(u => u.IsList ===true).map(function (e) {
return {
field: e.ColumnName,
title: e.Comment
};
});
columns.unshift({
type: 'checkbox',
fixed: 'left'
});
table.render({
elem: '#mainList',
page: true,
url: '/<%=ModuleName%>s/Load',
cols: [columns]
, response: {
statusCode: 200 //规定成功的状态码默认0
}
});
});
//主列表加载,可反复调用进行刷新
var config = {}; //table的参数如搜索key点击tree的id
var mainList = function(options) {
if (options != undefined) {
$.extend(config, options);
}
table.reload('mainList',
{
url: '/<%=ModuleName%>s/Load',
where: config
, response: {
statusCode: 200 //规定成功的状态码默认0
}
});
};
mainList();
//添加(编辑)对话框
var editDlg = function () {
var vm;
var update = false; //是否为更新
var show = function (data) {
var title = update ? "编辑信息" : "添加";
layer.open({
title: title,
area: ["500px", "400px"],
type: 1,
content: $('#divEdit'),
success: function () {
if(vm == undefined){
vm = new Vue({
el: "#formEdit",
data(){
return {
tmp:data //使用一个tmp封装一下后面可以直接用vm.tmp赋值
}
},
watch:{
tmp(val){
this.$nextTick(function () {
form.render(); //刷新select等
layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
})
}
},
mounted(){
form.render();
layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
}
});
}else{
vm.tmp = Object.assign({}, vm.tmp,data)
}
},
end: mainList
});
var url = "/<%=ModuleName%>s/Add";
if (update) {
url = "/<%=ModuleName%>s/Update";
}
//提交数据
form.on('submit(formSubmit)',
function (data) {
$.post(url,
data.field,
function (data) {
layer.msg(data.Message);
},
"json");
return false;
});
}
return {
add: function () { //弹出添加
update = false;
show({
Id: ''
});
},
update: function (data) { //弹出编辑框
update = true;
show(data);
}
};
}();
//监听表格内部按钮
table.on('tool(list)', function (obj) {
var data = obj.data;
if (obj.event === 'detail') { //查看
layer.msg('ID' + data.Id + ' 的查看操作');
}
});
//监听页面主按钮操作
var active = {
btnDel: function () { //批量删除
var checkStatus = table.checkStatus('mainList')
, data = checkStatus.data;
openauth.del("/<%=ModuleName%>s/Delete",
data.map(function (e) { return e.Id; }),
mainList);
}
, btnAdd: function () { //添加
editDlg.add();
}
, btnEdit: function () { //编辑
var checkStatus = table.checkStatus('mainList')
, data = checkStatus.data;
if (data.length != 1) {
layer.msg("请选择编辑的行,且同时只能编辑一行");
return;
}
editDlg.update(data[0]);
}
, search: function () { //搜索
mainList({ key: $('#key').val() });
}
, btnRefresh: function () {
mainList();
}
};
$('.toolList .layui-btn').on('click', function () {
var type = $(this).data('type');
active[type] ? active[type].call(this) : '';
});
//监听页面主按钮操作 end
})

View File

@ -0,0 +1,130 @@
<%--
Author: yubaolee
Description: 用于生成OpenAuth.Core开源版前端Web界面包括mvc controller/csthml/js
--%>
<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="None" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Assembly Name="Mono.Cecil" Path="..\Common" %>
<%@ Assembly Name="ICSharpCode.NRefactory" Path="..\Common" %>
<%@ Assembly Name="ICSharpCode.NRefactory.CSharp" Path="..\Common" %>
<%@ Assembly Src="Internal\Model.cs" %>
<%@ Assembly Src="Internal\Extensions.cs" %>
<%@ Assembly Src="Internal\Generator.cs" %>
<%@ Assembly Src="Internal\Parser.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<%@ Import Namespace="SchemaMapper" %>
<%@ Property Name="SourceTable"
Type="SchemaExplorer.TableSchema"
Category="Context"
Description="连接的数据库"
OnChanged="OnSourceDatabaseChanged"%>
<%@ Property Name="ModuleName"
Type="System.String"
Description="模块名称User"%>
<%@ Property Name="directory"
Type="System.String"
Default=".\"
Optional="True"
Description="代码生成路径"
Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
<%@ Register Name="HtmlGenerateClass"
Template="Web\Index.cshtml.cst"
MergeProperties="False" %>
<%@ Register Name="JSGenerateClass"
Template="Web\index.js.cst"
MergeProperties="False" %>
<%@ Register Name="ControllerGenerateClass"
Template="Web\Controller.cst"
MergeProperties="False" %>
Generating Entities ...
<% Generate(); %>
<script runat="template">
public void Generate()
{
Stopwatch watch = Stopwatch.StartNew();
string outputDirectory = Path.GetFullPath(directory);
CreateControllerClass();
CreateHtmlClass();
CreateJSClass();
this.RegisterReference("System.Configuration");
this.RegisterReference("System.Data");
this.RegisterReference("System.Data.Entity");
this.RegisterReference("System.Runtime.Serialization");
this.RegisterReference("EntityFramework");
watch.Stop();
Response.WriteLine("Generate Time: " + watch.ElapsedMilliseconds + " ms");
}
//创建控制器,如UserManagerController.cs
public void CreateControllerClass()
{
ControllerGenerateClass generatedClass = this.Create<ControllerGenerateClass>();
this.CopyPropertiesTo(generatedClass);
string rootDirectory = Path.GetFullPath(directory);
string generatedFile = Path.GetFullPath(directory) + "/Controllers/"+ ModuleName + "sController.cs";
generatedClass.ModuleName = ModuleName;
Response.WriteLine(generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
//创建视图,如views/Users/index.html
public void CreateHtmlClass()
{
HtmlGenerateClass generatedClass = this.Create<HtmlGenerateClass>();
this.CopyPropertiesTo(generatedClass);
string generatedFile = Path.GetFullPath(directory) + "/Views/"+ModuleName+"s/index.cshtml";
generatedClass.ModuleName = ModuleName;
generatedClass.SourceTable = SourceTable;
Response.WriteLine(generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
//创建视图,如js/userManager.js
public void CreateJSClass()
{
JSGenerateClass generatedClass = this.Create<JSGenerateClass>();
this.CopyPropertiesTo(generatedClass);
string generatedFile = Path.GetFullPath(directory) + "/userJs/"+ModuleName.ToLower()+"s.js";
generatedClass.ModuleName = ModuleName;
Response.WriteLine(generatedFile);
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
//更换数据源时改变ModuleName
private void OnSourceDatabaseChanged(object sender, EventArgs e)
{
if (SourceTable == null)
return;
ModuleName = SourceTable.Name;
}
</script>

Binary file not shown.

Binary file not shown.

Binary file not shown.

36
Dockerfile Normal file
View File

@ -0,0 +1,36 @@
##See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
#FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
#WORKDIR /app
#EXPOSE 10010
#
#COPY . .
#ENV ASPNETCORE_URLS=http://+:10010
#ENTRYPOINT ["dotnet", "/app/OpenAuth.WebApi.dll"]
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 10010
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["OpenAuth.WebApi/OpenAuth.WebApi.csproj", "OpenAuth.WebApi/"]
COPY ["Infrastructure/Infrastructure.csproj", "Infrastructure/"]
COPY ["OpenAuth.App/OpenAuth.App.csproj", "OpenAuth.App/"]
COPY ["OpenAuth.Repository/OpenAuth.Repository.csproj", "OpenAuth.Repository/"]
RUN dotnet restore "OpenAuth.WebApi/OpenAuth.WebApi.csproj"
COPY . .
WORKDIR "/src/OpenAuth.WebApi"
RUN dotnet build "OpenAuth.WebApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "OpenAuth.WebApi.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS=http://+:10010
ENTRYPOINT ["dotnet", "OpenAuth.WebApi.dll"]

View File

@ -0,0 +1,55 @@
using System.Collections.Generic;
namespace Infrastructure
{
/// <summary>
/// 配置项
/// </summary>
public class AppSetting
{
public AppSetting()
{
SSOPassport = "http://localhost:52789";
Version = "";
UploadPath = "";
IdentityServerUrl = "";
}
/// <summary>
/// SSO地址
/// </summary>
public string SSOPassport { get; set; }
/// <summary>
/// 版本信息
/// 如果为demo,则屏蔽Post请求
/// </summary>
public string Version { get; set; }
/// <summary>
/// 数据库类型 SqlServer、MySql
/// </summary>
public Dictionary<string, string> DbTypes { get; set; }
/// <summary> 附件上传路径</summary>
public string UploadPath { get; set; }
//identity授权的地址
public string IdentityServerUrl { get; set; }
/// <summary>
/// Redis服务器配置
/// </summary>
//public string RedisConf { get; set; }
public RedisConf RedisConf { get; set; }
//是否是Identity授权方式
public bool IsIdentityAuth => !string.IsNullOrEmpty(IdentityServerUrl);
}
public class RedisConf
{
public string Conn { get; set; }
public int Database { get; set; }
}
}

View File

@ -0,0 +1,74 @@
// ***********************************************************************
// Assembly : FairUtility
// Author : Yubao Li
// Created : 08-27-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 08-27-2015
// ***********************************************************************
// <copyright file="AutoMapperExt.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using AutoMapper;
using System.Collections;
using System.Collections.Generic;
namespace Infrastructure
{
public static class AutoMapperExt
{
/// <summary>
/// 类型映射
/// </summary>
public static T MapTo<T>(this object obj)
{
if (obj == null) return default(T);
var config = new MapperConfiguration(cfg=>cfg.CreateMap(obj.GetType(),typeof(T)));
var mapper = config.CreateMapper();
return mapper.Map<T>(obj);
}
/// <summary>
/// 集合列表类型映射
/// </summary>
public static List<TDestination> MapToList<TDestination>(this IEnumerable source)
{
Type sourceType = source.GetType().GetGenericArguments()[0]; //获取枚举的成员类型
var config = new MapperConfiguration(cfg => cfg.CreateMap(sourceType, typeof(TDestination)));
var mapper = config.CreateMapper();
return mapper.Map<List<TDestination>>(source);
}
/// <summary>
/// 集合列表类型映射
/// </summary>
public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
{
var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
var mapper = config.CreateMapper();
return mapper.Map<List<TDestination>>(source);
}
/// <summary>
/// 类型映射
/// </summary>
public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
where TSource : class
where TDestination : class
{
if (source == null) return destination;
var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
var mapper = config.CreateMapper();
return mapper.Map<TDestination>(source);
}
}
}

View File

@ -0,0 +1,88 @@
// ***********************************************************************
// Assembly : Helper
// Author : yubaolee
// Created : 12-16-2016
//
// Last Modified By : yubaolee
// Last Modified On : 12-21-2016
// 使用微软默认带超时的Cache
// File: CacheContext.cs
// ***********************************************************************
using System;
using System.Collections.Concurrent;
using Microsoft.Extensions.Caching.Memory;
namespace Infrastructure.Cache
{
public class CacheContext : ICacheContext
{
private IMemoryCache _objCache;
private static readonly ConcurrentDictionary<string, ConcurrentQueue<string>> queueDic = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
public CacheContext(IMemoryCache objCache)
{
_objCache = objCache;
}
public override T Get<T>(string key)
{
return _objCache.Get<T>(key);
}
public override bool Set<T>(string key, T t, DateTime expire)
{
var obj = Get<T>(key);
if (obj != null)
{
Remove(key);
}
_objCache.Set(key, t, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(expire)); //绝对过期时间
return true;
}
public override bool Remove(string key)
{
_objCache.Remove(key);
return true;
}
/// <summary>
/// 添加并发锁
/// </summary>
/// <param name="id">值</param>
/// <param name="func">执行方法</param>
/// <param name="key">键</param>
/// <returns></returns>
public override async Task<T> Lock<T>(string id, Func<string, Task<T>> func, string key = "hc")
{
var queue = queueDic.GetOrAdd(id, new ConcurrentQueue<string>());
var token = Guid.NewGuid().ToString();
queue.Enqueue(token);
queue.TryPeek(out string newToken);
if (token != newToken)
{
while (true)
{
Thread.Sleep(10);
queue.TryPeek(out newToken);
if (token == newToken)
{
break;
}
}
}
try
{
return await func(id);
}
finally
{
queue.TryDequeue(out string _);
}
}
}
}

View File

@ -0,0 +1,55 @@
// ***********************************************************************
// Assembly : Infrastructure
// Author : yubaolee
// Created : 06-21-2016
//
// Last Modified By : yubaolee
// Last Modified On : 06-21-2016
// Contact : Add services.AddEnyimMemcached(...)
// and app.UseEnyimMemcached() in Startup.
// File: EnyimMemcachedContext.cs
// ***********************************************************************
using System;
using Enyim.Caching;
using Enyim.Caching.Memcached;
namespace Infrastructure.Cache
{
public sealed class EnyimMemcachedContext : ICacheContext
{
private IMemcachedClient _memcachedClient;
public EnyimMemcachedContext(IMemcachedClient client)
{
_memcachedClient = client;
}
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public override T Get<T>(string key)
{
return _memcachedClient.Get<T>(key);
}
public override bool Set<T>(string key, T t, DateTime expire)
{
return _memcachedClient.Store(StoreMode.Set, key, t, expire);
}
public override bool Remove(string key)
{
return _memcachedClient.Remove(key);
}
public override Task<T> Lock<T>(string id, Func<string, Task<T>> func, string key = "hc")
{
return func(id);
}
}
}

View File

@ -0,0 +1,36 @@
using System;
namespace Infrastructure.Cache
{
/// <summary>
/// 缓存接口
/// </summary>
public abstract class ICacheContext
{
/// <summary>
/// 获取缓存项
/// </summary>
/// <typeparam name="T">缓存对象类型</typeparam>
/// <param name="key">键</param>
/// <returns>缓存对象</returns>
public abstract T Get<T>(string key);
/// <summary>
/// 设置缓存项
/// </summary>
/// <typeparam name="T">缓存对象类型</typeparam>
/// <param name="key">键</param>
/// <param name="t">缓存对象</param>
/// <returns>true成功,false失败</returns>
public abstract bool Set<T>(string key, T t, DateTime expire);
/// <summary>
/// 移除一个缓存项
/// </summary>
/// <param name="key">缓存项key</param>
/// <returns>true成功,false失败</returns>
public abstract bool Remove(string key);
public abstract Task<T> Lock<T>(string id, Func<string, Task<T>> func, string key = "hc");
}
}

View File

@ -0,0 +1,63 @@
using System;
using Enyim.Caching;
using Enyim.Caching.Memcached;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
namespace Infrastructure.Cache
{
/// <summary>
/// 缓存redis实现
/// </summary>
public sealed class RedisCacheContext : ICacheContext
{
private ConnectionMultiplexer _conn { get; set; }
private IDatabase iDatabase { get; set; }
public RedisCacheContext(IOptions<AppSetting> options)
{
_conn = ConnectionMultiplexer.Connect(options.Value.RedisConf.Conn);
iDatabase = _conn.GetDatabase(options.Value.RedisConf.Database);
}
public override T Get<T>(string key)
{
RedisValue value = iDatabase.StringGet(key);
if (!value.HasValue)
{
return default(T);
}
if (typeof(T) == typeof(string))
{
return (T)Convert.ChangeType(value, typeof(T));
}
else
{
return JsonHelper.Instance.Deserialize<T>(value);
}
}
public override bool Set<T>(string key, T t, DateTime expire)
{
if (typeof(T) == typeof(string))
{
return iDatabase.StringSet(key, t.ToString(), expire - DateTime.Now);
}
else
{
return iDatabase.StringSet(key, JsonHelper.Instance.Serialize(t), expire - DateTime.Now);
}
}
public override bool Remove(string key)
{
return iDatabase.KeyDelete(key);
}
public override Task<T> Lock<T>(string id, Func<string, Task<T>> func, string key = "hc")
{
return func(id);
}
}
}

View File

@ -0,0 +1,22 @@

using System;
namespace Infrastructure
{
public class CommonException : Exception
{
private int _code;
public CommonException(string message, int code)
: base(message)
{
this._code = code;
}
public int Code
{
get { return _code; }
}
}
}

View File

@ -0,0 +1,30 @@
namespace Infrastructure.Const
{
/// <summary>
/// 流程状态
/// </summary>
public struct FlowInstanceStatus
{
/// <summary>
/// 撤销、召回
/// </summary>
public const int Draft = -1;
/// <summary>
/// 正在运行
/// </summary>
public const int Running = 0;
/// <summary>
/// 完成
/// </summary>
public const int Finished = 1;
/// <summary>
/// 不同意
/// </summary>
public const int Disagree = 3;
/// <summary>
/// 驳回
/// </summary>
public const int Rejected = 4;
}
}

View File

@ -0,0 +1,26 @@
namespace Infrastructure.Const
{
public struct HtmlElementType
{
public const string drop = "drop";
public const string droplist = "droplist";
public const string select = "select";
public const string selectlist = "selectlist";
public const string checkbox = "checkbox";
public const string textarea = "textarea";
public const string thanorequal = "thanorequal";
public const string lessorequal = "lessorequal";
public const string gt = "gt";
public const string lt = "lt";
public const string GT = ">";
public const string LT = "<";
public const string like = "like";
public const string ThanOrEqual = ">=";
public const string LessOrequal = "<=";
public const string Contains = "in";
public const string Equal = "=";
}
}

View File

@ -0,0 +1,17 @@
namespace Infrastructure.Const
{
/// <summary>
/// 定时任务状态
/// </summary>
public enum JobStatus
{
/// <summary>
/// 未启动
/// </summary>
NotRun,
/// <summary>
/// 正在运行
/// </summary>
Running
}
}

View File

@ -0,0 +1,15 @@
namespace Infrastructure.Const
{
public enum LinqExpressionType
{
Equal=0,//=
NotEqual=1,//!=
GreaterThan,//>
LessThan,//<
ThanOrEqual,//>=
LessThanOrEqual,//<=
In,
Contains,//Contains
NotContains//NotContains
}
}

View File

@ -0,0 +1,8 @@
namespace Infrastructure.Const
{
public enum QueryOrderBy
{
Desc=1,
Asc=2
}
}

View File

@ -0,0 +1,27 @@
namespace Infrastructure.Const
{
public enum ResponseType
{
ServerError = 1,
LoginExpiration = 302,
ParametersLack = 303,
TokenExpiration,
PINError,
NoPermissions,
NoRolePermissions,
LoginError,
AccountLocked,
LoginSuccess,
SaveSuccess,
AuditSuccess,
OperSuccess,
RegisterSuccess,
ModifyPwdSuccess,
EidtSuccess,
DelSuccess,
NoKey,
NoKeyDel,
KeyError,
Other
}
}

View File

@ -0,0 +1,24 @@
namespace Infrastructure.Const
{
public struct SqlDbTypeName
{
public const string NVarChar = "nvarchar";
public const string VarChar = "varchar";
public const string NChar = "nchar";
public const string Char = "char";
public const string Text = "text";
public const string Int = "int";
public const string BigInt = "bigint";
public const string DateTime = "datetime";
public const string Date = "date";
public const string SmallDateTime = "smalldatetime";
public const string SmallDate = "smalldate";
public const string Float = "float";
public const string Decimal = "decimal";
public const string Double = "double";
public const string Bit = "bit";
public const string Bool = "bool";
public const string UniqueIdentifier = "uniqueidentifier";
}
}

View File

@ -0,0 +1,412 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Infrastructure.Extensions;
namespace Infrastructure.Database
{
/// <summary>
/// 数据库数据转换拓展
/// </summary>
public static class DbDataConvertExtensions
{
/// <summary>
/// 将 DataTable 转 List 集合
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="dataTable">DataTable</param>
/// <returns>List{T}</returns>
public static List<T> ToList<T>(this DataTable dataTable)
{
return dataTable.ToList(typeof(List<T>)) as List<T>;
}
/// <summary>
/// 将 DataTable 转 List 集合
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="dataTable">DataTable</param>
/// <returns>List{T}</returns>
public static async Task<List<T>> ToListAsync<T>(this DataTable dataTable)
{
var list = await dataTable.ToListAsync(typeof(List<T>));
return list as List<T>;
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static List<T1> ToList<T1>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>));
return tuple[0] as List<T1>;
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2) ToList<T1, T2>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3) ToList<T1, T2, T3>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <typeparam name="T4">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3, List<T4> list4) ToList<T1, T2, T3, T4>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>), typeof(List<T4>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>, tuple[3] as List<T4>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <typeparam name="T4">元组元素类型</typeparam>
/// <typeparam name="T5">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3, List<T4> list4, List<T5> list5) ToList<T1, T2, T3, T4, T5>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>), typeof(List<T4>), typeof(List<T5>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>, tuple[3] as List<T4>, tuple[4] as List<T5>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <typeparam name="T4">元组元素类型</typeparam>
/// <typeparam name="T5">元组元素类型</typeparam>
/// <typeparam name="T6">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3, List<T4> list4, List<T5> list5, List<T6> list6) ToList<T1, T2, T3, T4, T5, T6>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>), typeof(List<T4>), typeof(List<T5>), typeof(List<T6>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>, tuple[3] as List<T4>, tuple[4] as List<T5>, tuple[5] as List<T6>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <typeparam name="T4">元组元素类型</typeparam>
/// <typeparam name="T5">元组元素类型</typeparam>
/// <typeparam name="T6">元组元素类型</typeparam>
/// <typeparam name="T7">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3, List<T4> list4, List<T5> list5, List<T6> list6, List<T7> list7) ToList<T1, T2, T3, T4, T5, T6, T7>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>), typeof(List<T4>), typeof(List<T5>), typeof(List<T6>), typeof(List<T7>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>, tuple[3] as List<T4>, tuple[4] as List<T5>, tuple[5] as List<T6>, tuple[6] as List<T7>);
}
/// <summary>
/// 将 DataSet 转 元组
/// </summary>
/// <typeparam name="T1">元组元素类型</typeparam>
/// <typeparam name="T2">元组元素类型</typeparam>
/// <typeparam name="T3">元组元素类型</typeparam>
/// <typeparam name="T4">元组元素类型</typeparam>
/// <typeparam name="T5">元组元素类型</typeparam>
/// <typeparam name="T6">元组元素类型</typeparam>
/// <typeparam name="T7">元组元素类型</typeparam>
/// <typeparam name="T8">元组元素类型</typeparam>
/// <param name="dataSet">DataSet</param>
/// <returns>元组类型</returns>
public static (List<T1> list1, List<T2> list2, List<T3> list3, List<T4> list4, List<T5> list5, List<T6> list6, List<T7> list7, List<T8> list8) ToList<T1, T2, T3, T4, T5, T6, T7, T8>(this DataSet dataSet)
{
var tuple = dataSet.ToList(typeof(List<T1>), typeof(List<T2>), typeof(List<T3>), typeof(List<T4>), typeof(List<T5>), typeof(List<T6>), typeof(List<T7>), typeof(List<T8>));
return (tuple[0] as List<T1>, tuple[1] as List<T2>, tuple[2] as List<T3>, tuple[3] as List<T4>, tuple[4] as List<T5>, tuple[5] as List<T6>, tuple[6] as List<T7>, tuple[7] as List<T8>);
}
/// <summary>
/// 将 DataSet 转 特定类型
/// </summary>
/// <param name="dataSet">DataSet</param>
/// <param name="returnTypes">特定类型集合</param>
/// <returns>List{object}</returns>
public static List<object> ToList(this DataSet dataSet, params Type[] returnTypes)
{
if (returnTypes == null || returnTypes.Length == 0) return default;
// 处理元组类型
if (returnTypes.Length == 1 && returnTypes[0].IsValueType)
{
returnTypes = returnTypes[0].GenericTypeArguments;
}
// 获取所有的 DataTable
var dataTables = dataSet.Tables;
// 处理 8 个结果集
if (returnTypes.Length >= 8)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2]),
dataTables[3].ToList(returnTypes[3]),
dataTables[4].ToList(returnTypes[4]),
dataTables[5].ToList(returnTypes[5]),
dataTables[6].ToList(returnTypes[6]),
dataTables[7].ToList(returnTypes[7])
};
}
// 处理 7 个结果集
else if (returnTypes.Length == 7)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2]),
dataTables[3].ToList(returnTypes[3]),
dataTables[4].ToList(returnTypes[4]),
dataTables[5].ToList(returnTypes[5]),
dataTables[6].ToList(returnTypes[6])
};
}
// 处理 6 个结果集
else if (returnTypes.Length == 6)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2]),
dataTables[3].ToList(returnTypes[3]),
dataTables[4].ToList(returnTypes[4]),
dataTables[5].ToList(returnTypes[5])
};
}
// 处理 5 个结果集
else if (returnTypes.Length == 5)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2]),
dataTables[3].ToList(returnTypes[3]),
dataTables[4].ToList(returnTypes[4])
};
}
// 处理 4 个结果集
else if (returnTypes.Length == 4)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2]),
dataTables[3].ToList(returnTypes[3])
};
}
// 处理 3 个结果集
else if (returnTypes.Length == 3)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1]),
dataTables[2].ToList(returnTypes[2])
};
}
// 处理 2 个结果集
else if (returnTypes.Length == 2)
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0]),
dataTables[1].ToList(returnTypes[1])
};
}
// 处理 1 个结果集
else
{
return new List<object>
{
dataTables[0].ToList(returnTypes[0])
};
}
}
/// <summary>
/// 将 DataSet 转 特定类型
/// </summary>
/// <param name="dataSet">DataSet</param>
/// <param name="returnTypes">特定类型集合</param>
/// <returns>object</returns>
public static Task<List<object>> ToListAsync(this DataSet dataSet, params Type[] returnTypes)
{
return Task.FromResult(dataSet.ToList(returnTypes));
}
/// <summary>
/// 将 DataTable 转 特定类型
/// </summary>
/// <param name="dataTable">DataTable</param>
/// <param name="returnType">返回值类型</param>
/// <returns>object</returns>
public static object ToList(this DataTable dataTable, Type returnType)
{
var isGenericType = returnType.IsGenericType;
// 获取类型真实返回类型
var underlyingType = isGenericType ? returnType.GenericTypeArguments.First() : returnType;
var resultType = typeof(List<>).MakeGenericType(underlyingType);
var list = Activator.CreateInstance(resultType);
var addMethod = resultType.GetMethod("Add");
// 将 DataTable 转为行集合
var dataRows = dataTable.AsEnumerable();
// 如果是基元类型
if (underlyingType.IsRichPrimitive())
{
// 遍历所有行
foreach (var dataRow in dataRows)
{
// 只取第一列数据
var firstColumnValue = dataRow[0];
// 转换成目标类型数据
var destValue = firstColumnValue?.ChangeType(underlyingType);
// 添加到集合中
_ = addMethod.Invoke(list, new[] { destValue });
}
}
// 处理Object类型
else if (underlyingType == typeof(object))
{
// 获取所有列名
var columns = dataTable.Columns;
// 遍历所有行
foreach (var dataRow in dataRows)
{
var dic = new Dictionary<string, object>();
foreach (DataColumn column in columns)
{
dic.Add(column.ColumnName, dataRow[column]);
}
_ = addMethod.Invoke(list, new[] { dic });
}
}
else
{
// 获取所有的数据列和类公开实例属性
var dataColumns = dataTable.Columns;
var properties = underlyingType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
//.Where(p => !p.IsDefined(typeof(NotMappedAttribute), true)); // sql 数据转换无需判断 [NotMapperd] 特性
// 遍历所有行
foreach (var dataRow in dataRows)
{
var model = Activator.CreateInstance(underlyingType);
// 遍历所有属性并一一赋值
foreach (var property in properties)
{
// 获取属性对应的真实列名
var columnName = property.Name;
if (property.IsDefined(typeof(ColumnAttribute), true))
{
var columnAttribute = property.GetCustomAttribute<ColumnAttribute>(true);
if (!string.IsNullOrWhiteSpace(columnAttribute.Name)) columnName = columnAttribute.Name;
}
// 如果 DataTable 不包含该列名,则跳过
if (!dataColumns.Contains(columnName)) continue;
// 获取列值
var columnValue = dataRow[columnName];
// 如果列值未空,则跳过
if (columnValue == DBNull.Value) continue;
// 转换成目标类型数据
var destValue = columnValue?.ChangeType(property.PropertyType);
property.SetValue(model, destValue);
}
// 添加到集合中
_ = addMethod.Invoke(list, new[] { model });
}
}
return list;
}
/// <summary>
/// 将 DataTable 转 特定类型
/// </summary>
/// <param name="dataTable">DataTable</param>
/// <param name="returnType">返回值类型</param>
/// <returns>object</returns>
public static Task<object> ToListAsync(this DataTable dataTable, Type returnType)
{
return Task.FromResult(dataTable.ToList(returnType));
}
/// <summary>
/// 处理元组类型返回值
/// </summary>
/// <param name="dataSet">数据集</param>
/// <param name="tupleType">返回值类型</param>
/// <returns></returns>
internal static object ToValueTuple(this DataSet dataSet, Type tupleType)
{
// 获取元组最底层类型
var underlyingTypes = tupleType.GetGenericArguments().Select(u => u.IsGenericType ? u.GetGenericArguments().First() : u);
var toListMethod = typeof(DbDataConvertExtensions)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(u => u.Name == "ToList" && u.IsGenericMethod && u.GetGenericArguments().Length == tupleType.GetGenericArguments().Length)
.MakeGenericMethod(underlyingTypes.ToArray());
return toListMethod.Invoke(null, new[] { dataSet });
}
}
}

38
Infrastructure/Define.cs Normal file
View File

@ -0,0 +1,38 @@
namespace Infrastructure
{
public static class Define
{
public static string USERROLE = "UserRole"; //用户角色关联KEY
public const string ROLERESOURCE = "RoleResource"; //角色资源关联KEY
public const string USERORG = "UserOrg"; //用户机构关联KEY
public const string ROLEELEMENT = "RoleElement"; //角色菜单关联KEY
public const string ROLEMODULE = "RoleModule"; //角色模块关联KEY
public const string ROLEDATAPROPERTY = "RoleDataProperty"; //角色数据字段权限
public const string DBTYPE_SQLSERVER = "SqlServer"; //sql server
public const string DBTYPE_MYSQL = "MySql"; //mysql
public const string DBTYPE_PostgreSQL = "PostgreSQL"; //PostgreSQL
public const string DBTYPE_ORACLE = "Oracle"; //oracle
public const int INVALID_TOKEN = 50014; //token无效
public const string TOKEN_NAME = "X-Token";
public const string TENANT_ID = "tenantId";
public const string SYSTEM_USERNAME = "System";
public const string SYSTEM_USERPWD = "acdcd3db09e0dc32c222c1840144e31d";
//public const string SYSTEM_USERPWD = "6ff33dd3478bae96663aced32f5262fa";
public const string SYSTEM_SECRETKEY = "b6467189772775db";
public const string DATAPRIVILEGE_LOGINUSER = "{loginUser}"; //数据权限配置中当前登录用户的key
public const string DATAPRIVILEGE_LOGINROLE = "{loginRole}"; //数据权限配置中当前登录用户角色的key
public const string DATAPRIVILEGE_LOGINORG = "{loginOrg}"; //数据权限配置中当前登录用户部门的key
public const string JOBMAPKEY = "OpenJob";
public const string DEFAULT_FORM_INSTANCE_ID_NAME = "InstanceId";
}
}

View File

@ -0,0 +1,306 @@
// ***********************************************************************
// Assembly : FairUtility
// Author : Yubao Li
// Created : 08-18-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 08-18-2015
// ***********************************************************************
// <copyright file="DynamicLinq.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary>动态linq</summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Infrastructure
{
public static class DynamicLinq
{
public static ParameterExpression CreateLambdaParam<T>(string name)
{
return Expression.Parameter(typeof(T), name);
}
/// <summary>
/// 创建linq表达示的body部分
/// </summary>
public static Expression GenerateBody<T>(this ParameterExpression param, Filter filterObj)
{
PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
Expression left = null; //组装左边
//组装右边
Expression right = null;
if (property != null)
{
left = Expression.Property(param, property);
if (property.PropertyType == typeof(int))
{
right = Expression.Constant(int.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(DateTime))
{
right = Expression.Constant(DateTime.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(string))
{
right = Expression.Constant(filterObj.Value);
}
else if (property.PropertyType == typeof(decimal))
{
right = Expression.Constant(decimal.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(Guid))
{
right = Expression.Constant(Guid.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(bool))
{
right = Expression.Constant(filterObj.Value.Equals("1"));
}
else if (property.PropertyType == typeof(Guid?))
{
left = Expression.Property(left, "Value");
right = Expression.Constant(Guid.Parse(filterObj.Value));
}
else
{
throw new Exception("暂不能解析该Key的类型");
}
}
else //如果左边不是属性,直接是值的情况
{
left = Expression.Constant(filterObj.Key);
right = Expression.Constant(filterObj.Value);
}
//c.XXX=="XXX"
Expression filter = Expression.Equal(left, right);
switch (filterObj.Contrast)
{
case "<=":
filter = Expression.LessThanOrEqual(left, right);
break;
case "<":
filter = Expression.LessThan(left, right);
break;
case ">":
filter = Expression.GreaterThan(left, right);
break;
case ">=":
filter = Expression.GreaterThanOrEqual(left, right);
break;
case "!=":
filter = Expression.NotEqual(left, right);
break;
case "contains":
filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] {typeof(string)}),
Expression.Constant(filterObj.Value));
break;
case "in":
var lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var methodInfo = typeof(List<string>).GetMethod("Contains",
new Type[] {typeof(string)}); //Contains语句
filter = Expression.Call(lExp, methodInfo, left);
break;
case "not in":
var listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var method = typeof(List<string>).GetMethod("Contains", new Type[] {typeof(string)}); //Contains语句
filter = Expression.Not(Expression.Call(listExpression, method, left));
break;
//交集,使用交集时左值必须时固定的值
case "intersect": //交集
if (property != null)
{
throw new Exception("交集模式下,表达式左边不能为变量,请调整数据规则,如:c=>\"A,B,C\" intersect \"B,D\"");
}
var rightval = filterObj.Value.Split(',').ToList();
var leftval = filterObj.Key.Split(',').ToList();
var val = rightval.Intersect(leftval);
filter = Expression.Constant(val.Count() > 0);
break;
}
return filter;
}
public static Expression<Func<T, bool>> GenerateTypeBody<T>(this ParameterExpression param, Filter filterObj)
{
return (Expression<Func<T, bool>>) (param.GenerateBody<T>(filterObj));
}
/// <summary>
/// 创建完整的lambda
/// </summary>
public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body)
{
//c=>c.XXX=="XXX"
return Expression.Lambda(body, param);
}
public static Expression<Func<T, bool>> GenerateTypeLambda<T>(this ParameterExpression param, Expression body)
{
return (Expression<Func<T, bool>>) (param.GenerateLambda(body));
}
public static Expression AndAlso(this Expression expression, Expression expressionRight)
{
return Expression.AndAlso(expression, expressionRight);
}
public static Expression Or(this Expression expression, Expression expressionRight)
{
return Expression.Or(expression, expressionRight);
}
public static Expression And(this Expression expression, Expression expressionRight)
{
return Expression.And(expression, expressionRight);
}
public static IQueryable<T> GenerateFilter<T>(this IQueryable<T> query, string parametername, string filterjson)
{
if (!string.IsNullOrEmpty(filterjson))
{
var filterGroup = JsonHelper.Instance.Deserialize<FilterGroup>(filterjson);
query = GenerateFilter(query, parametername, filterGroup);
}
return query;
}
/// <summary>
/// 转换FilterGroup为Lambda表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="parametername"></param>
/// <param name="filterGroup"></param>
/// <returns></returns>
public static IQueryable<T> GenerateFilter<T>(this IQueryable<T> query, string parametername,
FilterGroup filterGroup)
{
var param = CreateLambdaParam<T>(parametername);
Expression result = ConvertGroup<T>(filterGroup, param);
query = query.Where(param.GenerateTypeLambda<T>(result));
return query;
}
/// <summary>
/// 转换filtergroup为表达式
/// </summary>
/// <param name="filterGroup"></param>
/// <param name="param"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression ConvertGroup<T>(FilterGroup filterGroup, ParameterExpression param)
{
if (filterGroup == null) return null;
if (filterGroup.Filters.Length == 1 &&(filterGroup.Children == null || !filterGroup.Children.Any())) //只有一个条件
{
return param.GenerateBody<T>(filterGroup.Filters[0]);
}
Expression result = ConvertFilters<T>(filterGroup.Filters, param, filterGroup.Operation);
Expression gresult = ConvertGroup<T>(filterGroup.Children, param, filterGroup.Operation);
if (gresult == null) return result;
if (result == null) return gresult;
if (filterGroup.Operation == "and")
{
return result.AndAlso(gresult);
}
else //or
{
return result.Or(gresult);
}
}
/// <summary>
/// 转换FilterGroup[]为表达式不管FilterGroup里面的Filters
/// </summary>
/// <param name="groups"></param>
/// <param name="param"></param>
/// <param name="operation"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static Expression ConvertGroup<T>(FilterGroup[] groups, ParameterExpression param, string operation)
{
if (groups == null || !groups.Any()) return null;
Expression result = ConvertGroup<T>(groups[0], param);
if (groups.Length == 1) return result;
if (operation == "and")
{
foreach (var filter in groups.Skip(1))
{
result = result.AndAlso(ConvertGroup<T>(filter, param));
}
}
else
{
foreach (var filter in groups.Skip(1))
{
result = result.Or(ConvertGroup<T>(filter, param));
}
}
return result;
}
/// <summary>
/// 转换Filter数组为表达式
/// </summary>
/// <param name="filters"></param>
/// <param name="param"></param>
/// <param name="operation"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static Expression ConvertFilters<T>(Filter[] filters, ParameterExpression param, string operation)
{
if (filters == null || !filters.Any())
{
return null;
}
Expression result = param.GenerateBody<T>(filters[0]);
if (filters.Length == 1)
{
return result;
}
if (operation == "and")
{
foreach (var filter in filters.Skip(1))
{
result = result.AndAlso(param.GenerateBody<T>(filter));
}
}
else
{
foreach (var filter in filters.Skip(1))
{
result = result.Or(param.GenerateBody<T>(filter));
}
}
return result;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace Infrastructure
{
public class Encryption
{
private static string encryptKey = "4h!@w$rng,i#$@x1%)5^3(7*5P31/Ee0";
//默认密钥向量
private static byte[] Keys = { 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F };
/// <summary>
/// 加密
/// </summary>
/// <param name="encryptString"></param>
/// <returns></returns>
public static string Encrypt(string encryptString)
{
if (string.IsNullOrEmpty(encryptString))
return string.Empty;
RijndaelManaged rijndaelProvider = new RijndaelManaged();
rijndaelProvider.Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));
rijndaelProvider.IV = Keys;
ICryptoTransform rijndaelEncrypt = rijndaelProvider.CreateEncryptor();
byte[] inputData = Encoding.UTF8.GetBytes(encryptString);
byte[] encryptedData = rijndaelEncrypt.TransformFinalBlock(inputData, 0, inputData.Length);
return Convert.ToBase64String(encryptedData);
}
/// <summary>
/// 解密
/// </summary>
/// <param name="decryptString"></param>
/// <returns></returns>
public static string Decrypt(string decryptString)
{
if (string.IsNullOrEmpty(decryptString))
return string.Empty;
try
{
RijndaelManaged rijndaelProvider = new RijndaelManaged();
rijndaelProvider.Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));
rijndaelProvider.IV = Keys;
ICryptoTransform rijndaelDecrypt = rijndaelProvider.CreateDecryptor();
byte[] inputData = Convert.FromBase64String(decryptString);
byte[] decryptedData = rijndaelDecrypt.TransformFinalBlock(inputData, 0, inputData.Length);
return Encoding.UTF8.GetString(decryptedData);
}
catch
{
return "";
}
}
}
}

View File

@ -0,0 +1,22 @@
using System;
namespace Infrastructure.Extensions.AutofacManager
{
/// <summary>
/// 提供全局静态获取服务的能力。
/// <para>例AutofacContainerModule.GetService&lt;IPathProvider&gt;()</para>
/// </summary>
public class AutofacContainerModule
{
static private IServiceProvider _provider;
public static void ConfigServiceProvider(IServiceProvider serviceProvider)
{
_provider = serviceProvider;
}
public static TService GetService<TService>() where TService:class
{
Type typeParameterType = typeof(TService);
return (TService)_provider.GetService(typeParameterType);
}
}
}

View File

@ -0,0 +1,9 @@
namespace Infrastructure.Extensions.AutofacManager
{
/// <summary>
/// 所有AutoFac注入的基类
/// </summary>
public interface IDependency
{
}
}

View File

@ -0,0 +1,377 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;
namespace Infrastructure.Extensions
{
public static class ConvertJsonExtension
{
#region 私有方法
/// <summary>
/// 过滤特殊字符
/// </summary>
/// <param name="s">字符串</param>
/// <returns>json字符串</returns>
private static string String2Json(String s)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
char c = s.ToCharArray()[i];
switch (c)
{
case '\"':
sb.Append("\\\""); break;
case '\\':
sb.Append("\\\\"); break;
case '/':
sb.Append("\\/"); break;
case '\b':
sb.Append("\\b"); break;
case '\f':
sb.Append("\\f"); break;
case '\n':
sb.Append("\\n"); break;
case '\r':
sb.Append("\\r"); break;
case '\t':
sb.Append("\\t"); break;
default:
sb.Append(c); break;
}
}
return sb.ToString();
}
/// <summary>
/// 格式化字符型、日期型、布尔型
/// </summary>
/// <param name="str"></param>
/// <param name="type"></param>
/// <returns></returns>
private static string StringFormat(string str, Type type)
{
if (type == typeof(string))
{
str = String2Json(str);
str = "\"" + str + "\"";
}
else if (type == typeof(DateTime))
{
str = "\"" + str + "\"";
}
else if (type == typeof(bool))
{
str = str.ToLower();
}
else if (type != typeof(string) && string.IsNullOrEmpty(str))
{
str = "\"" + str + "\"";
}
return str;
}
#endregion
#region list转换成JSON
/// <summary>
/// list转换为Json
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static string ListToJson<T>(this IList<T> list)
{
object obj = list[0];
return ListToJson<T>(list, obj.GetType().Name);
}
/// <summary>
/// list转换为json
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="p"></param>
/// <returns></returns>
private static string ListToJson<T>(this IList<T> list, string JsonName)
{
if (list.Count == 0)
{
return "";
}
StringBuilder Json = new StringBuilder();
if (string.IsNullOrEmpty(JsonName))
JsonName = list[0].GetType().Name;
Json.Append("{\"" + JsonName + "\":[");
for (int i = 0; i < list.Count; i++)
{
T obj = Activator.CreateInstance<T>();
PropertyInfo[] pi = obj.GetType().GetProperties();
Json.Append("{");
for (int j = 0; j < pi.Length; j++)
{
Type type = pi[j].GetValue(list[i], null).GetType();
Json.Append("\"" + pi[j].Name.ToString() + "\":" + StringFormat(pi[j].GetValue(list[i], null).ToString(), type));
if (j < pi.Length - 1)
{
Json.Append(",");
}
}
Json.Append("}");
if (i < list.Count - 1)
{
Json.Append(",");
}
}
Json.Append("]}");
return Json.ToString();
}
#endregion
#region 对象转换为Json
/// <summary>
/// 对象转换为json
/// </summary>
/// <param name="jsonObject">json对象</param>
/// <returns>json字符串</returns>
public static string ToJson(this object jsonObject)
{
string jsonString = "{";
PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties();
for (int i = 0; i < propertyInfo.Length; i++)
{
object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null);
string value = string.Empty;
if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan)
{
value = "'" + objectValue.ToString() + "'";
}
else if (objectValue is string)
{
value = "'" + ToJson(objectValue.ToString()) + "'";
}
else if (objectValue is IEnumerable)
{
value = ToJson((IEnumerable)objectValue);
}
else
{
value = ToJson(objectValue.ToString());
}
jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ",";
}
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
return jsonString + "}";
}
#endregion
#region 对象集合转换为json
/// <summary>
/// 对象集合转换为json
/// </summary>
/// <param name="array">对象集合</param>
/// <returns>json字符串</returns>
public static string ToJson(this IEnumerable array)
{
string jsonString = "{";
foreach (object item in array)
{
jsonString += ToJson(item) + ",";
}
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
return jsonString + "]";
}
#endregion
#region 普通集合转换Json
/// <summary>
/// 普通集合转换Json
/// </summary>
/// <param name="array">集合对象</param>
/// <returns>Json字符串</returns>
public static string ToArrayString(this IEnumerable array)
{
string jsonString = "[";
foreach (object item in array)
{
jsonString = ToJson(item.ToString()) + ",";
}
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
return jsonString + "]";
}
#endregion
#region DataSet转换为Json
/// <summary>
/// DataSet转换为Json
/// </summary>
/// <param name="dataSet">DataSet对象</param>
/// <returns>Json字符串</returns>
public static string ToJson(this DataSet dataSet)
{
string jsonString = "{";
foreach (DataTable table in dataSet.Tables)
{
jsonString += "\"" + table.TableName + "\":" + ToJson(table) + ",";
}
jsonString = jsonString.TrimEnd(',');
return jsonString + "}";
}
#endregion
#region Datatable转换为Json
/// <summary>
/// Datatable转换为Json
/// </summary>
/// <param name="table">Datatable对象</param>
/// <returns>Json字符串</returns>
public static string ToJson(this DataTable dt)
{
StringBuilder jsonString = new StringBuilder();
jsonString.Append("[");
DataRowCollection drc = dt.Rows;
for (int i = 0; i < drc.Count; i++)
{
jsonString.Append("{");
for (int j = 0; j < dt.Columns.Count; j++)
{
string strKey = dt.Columns[j].ColumnName;
string strValue = drc[i][j].ToString();
Type type = dt.Columns[j].DataType;
jsonString.Append("\"" + strKey + "\":");
strValue = StringFormat(strValue, type);
if (j < dt.Columns.Count - 1)
{
jsonString.Append(strValue + ",");
}
else
{
jsonString.Append(strValue);
}
}
jsonString.Append("},");
}
jsonString.Remove(jsonString.Length - 1, 1);
jsonString.Append("]");
return jsonString.ToString();
}
/// <summary>
/// DataTable转换为Json
/// </summary>
public static string ToJson(this DataTable dt, string jsonName)
{
StringBuilder Json = new StringBuilder();
if (string.IsNullOrEmpty(jsonName))
jsonName = dt.TableName;
Json.Append("{\"" + jsonName + "\":[");
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
Json.Append("{");
for (int j = 0; j < dt.Columns.Count; j++)
{
Type type = dt.Rows[i][j].GetType();
Json.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + StringFormat(dt.Rows[i][j].ToString(), type));
if (j < dt.Columns.Count - 1)
{
Json.Append(",");
}
}
Json.Append("}");
if (i < dt.Rows.Count - 1)
{
Json.Append(",");
}
}
}
Json.Append("]}");
return Json.ToString();
}
#endregion
#region DataReader转换为Json
/// <summary>
/// DataReader转换为Json
/// </summary>
/// <param name="dataReader">DataReader对象</param>
/// <returns>Json字符串</returns>
public static string ReaderJson(this IDataReader dataReader)
{
StringBuilder jsonString = new StringBuilder();
Dictionary<string, Type> ModelField = new Dictionary<string, Type>();
for (int i = 0; i < dataReader.FieldCount; i++)
{
ModelField.Add(dataReader.GetName(i), dataReader.GetFieldType(i));
}
jsonString.Append("[");
while (dataReader.Read())
{
jsonString.Append("{");
foreach (KeyValuePair<string, Type> keyVal in ModelField)
{
Type type = keyVal.Value;
string strKey = keyVal.Key;
string strValue = dataReader[strKey].ToString();
jsonString.Append("\"" + strKey + "\":");
strValue = StringFormat(strValue, type);
jsonString.Append(strValue + ",");
}
jsonString.Remove(jsonString.Length - 1, 1);
jsonString.Append("},");
}
dataReader.Close();
jsonString.Remove(jsonString.Length - 1, 1);
jsonString.Append("]");
return jsonString.ToString();
}
#endregion
public static T DeserializeObject<T>(this string entityString)
{
if (string.IsNullOrEmpty(entityString))
{
return default(T);
}
if (entityString == "{}")
{
entityString = "[]";
}
return JsonConvert.DeserializeObject<T>(entityString);
}
public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
{
if (obj == null) return null;
formatDate = formatDate ?? new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd HH:mm:ss"
};
return JsonConvert.SerializeObject(obj, formatDate);
}
//
// 摘要:
// 字串反序列化成指定对象实体(列表)
//
// 参数:
// Json:
// 字串
//
// 类型参数:
// T:
// 实体类型
public static List<T> ToList<T>(this string Json)
{
return (Json == null) ? null : JsonConvert.DeserializeObject<List<T>>(Json);
}
}
}

View File

@ -0,0 +1,52 @@
using System;
namespace Infrastructure.Extensions
{
public static class DateTimeExtension
{
/// <summary>
/// 实现由C# 的时间到 Javascript 的时间的转换
/// returns the number of milliseconds since Jan 1, 1970 (useful for converting C# dates to JS dates)
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static double UnixTicks(this DateTime dt)
{
DateTime d1 = new DateTime(1970, 1, 1);
DateTime d2 = dt.AddHours(8).ToUniversalTime();
TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks);
return ts.TotalMilliseconds;
}
/// <summary>
/// 将毫秒值转成 C# DateTime 类型
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public static DateTime ConvertTime(this long time)
{
DateTime timeStamp = new DateTime(1970, 1, 1); //得到1970年的时间戳
long t = (time + 8 * 60 * 60) * 10000000 + timeStamp.Ticks;
DateTime dt = new DateTime(t);
return dt;
}
/// <summary>
/// 获取格式化字符串,不带时分秒,格式:"yyyy-MM-dd"
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static string ToDateString(this DateTime? dateTime)
{
if (!dateTime.HasValue)
{
return string.Empty;
}
return dateTime.Value.ToDateString();
}
public static string ToDateString(this DateTime dateTime)
{
return dateTime.ToString("yyyy-MM-dd");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Extensions
{
public static class EnumTypeExtention
{
public static T GetEnumByName<T>(this string name)
{
foreach (var memberInfo in typeof(T).GetMembers())
{
foreach (var attr in memberInfo.GetCustomAttributes(true))
{
var test = attr as DisplayAttribute;
if (test == null) continue;
if (test.Name == name)
{
var result = (T)Enum.Parse(typeof(T), memberInfo.Name);
return result;
}
}
}
return default(T);
}
public static string GetEnumName<T>(this T type, Enum enm) where T : Type
{
foreach (var memberInfo in type.GetMembers())
{
foreach (var attr in memberInfo.GetCustomAttributes(true))
{
var test = attr as DisplayAttribute;
if (test == null) continue;
if (memberInfo.Name == enm.ToString())
{
return test.Name;
}
}
}
return null;
}
public static string GetDescription(this Enum val)
{
var field = val.GetType().GetField(val.ToString());
var customAttribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
if (customAttribute == null) { return val.ToString(); }
else { return ((DescriptionAttribute)customAttribute).Description; }
}
}
}

View File

@ -0,0 +1,22 @@
using Newtonsoft.Json.Converters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Extensions
{
public static class ExtensionsJson
{
//public static string ToJson(this object obj)
//{
// IsoDateTimeConverter isoDateTimeConverter = new IsoDateTimeConverter
// {
// DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
// };
// return JsonConvert.SerializeObject(obj, isoDateTimeConverter);
//}
}
}

View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Infrastructure.Extensions
{
/// <summary>
/// 泛型扩展
/// </summary>
public static class GenericExtension
{
public static bool Equal<T>(this T x, T y)
{
return ((IComparable)(x)).CompareTo(y) == 0;
}
#region ToDictionary
/// <summary>
/// 将实体指定的字段写入字典
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <param name="expression"></param>
/// <returns></returns>
public static Dictionary<string, object> ToDictionary<T>(this T t, Expression<Func<T, object>> expression) where T : class
{
Dictionary<string, object> dic = new Dictionary<string, object>();
string[] fields = expression.GetExpressionToArray();
PropertyInfo[] properties = expression == null ? t.GetType().GetProperties() : t.GetType().GetProperties().Where(x => fields.Contains(x.Name)).ToArray();
foreach (var property in properties)
{
var value = property.GetValue(t, null);
dic.Add(property.Name, value != null ? value.ToString() : "");
}
return dic;
}
public static Dictionary<string, string> ToDictionary<TInterface, T>(this TInterface t, Dictionary<string, string> dic = null) where T : class, TInterface
{
if (dic == null)
dic = new Dictionary<string, string>();
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(t, null);
if (value == null) continue;
dic.Add(property.Name, value != null ? value.ToString() : "");
}
return dic;
}
#endregion
public static DataTable ToDataTable<T>(this IEnumerable<T> source, Expression<Func<T, object>> columns = null, bool contianKey = true)
{
DataTable dtReturn = new DataTable();
if (source == null) return dtReturn;
PropertyInfo[] oProps = typeof(T).GetProperties()
.Where(x => x.PropertyType.Name != "List`1").ToArray();
if (columns != null)
{
string[] columnArray = columns.GetExpressionToArray();
oProps = oProps.Where(x => columnArray.Contains(x.Name)).ToArray();
}
//移除自增主键
PropertyInfo keyType = oProps.GetKeyProperty();// oProps.GetKeyProperty()?.PropertyType;
if (!contianKey && keyType != null && (keyType.PropertyType == typeof(int) || keyType.PropertyType == typeof(long)))
{
oProps = oProps.Where(x => x.Name != keyType.Name).ToArray();
}
foreach (var pi in oProps)
{
var colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
foreach (var rec in source)
{
var dr = dtReturn.NewRow();
foreach (var pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null
? DBNull.Value
: pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
}
}

View File

@ -0,0 +1,504 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Infrastructure.Const;
namespace Infrastructure.Extensions
{
public static class LambdaExtensions
{
/// <summary>
/// 分页查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryable"></param>
/// <param name="page"></param>
/// <param name="size"></param>
/// <returns></returns>
public static IQueryable<T> TakePage<T>(this IQueryable<T> queryable, int page, int size = 15)
{
return queryable.TakeOrderByPage<T>(page, size);
}
/// <summary>
/// 分页查询
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryable"></param>
/// <param name="page"></param>
/// <param name="size"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
public static IQueryable<T> TakeOrderByPage<T>(this IQueryable<T> queryable, int page, int size = 15, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null)
{
if (page <= 0)
{
page = 1;
}
return Queryable.Take(Queryable.Skip(queryable.GetIQueryableOrderBy(orderBy.GetExpressionToDic()), (page - 1) * size), size);
}
/// <summary>
/// 创建lambda表达式p=>true
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True<T>()
{
return p => true;
}
/// <summary>
/// 创建lambda表达式p=>false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False<T>()
{
return p => false;
}
public static ParameterExpression GetExpressionParameter(this Type type)
{
return Expression.Parameter(type, "p");
}
/// <summary>
/// 创建lambda表达式p=>p.propertyName
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="sort"></param>
/// <returns></returns>
public static Expression<Func<T, TKey>> GetExpression<T, TKey>(this string propertyName)
{
return propertyName.GetExpression<T, TKey>(typeof(T).GetExpressionParameter());
}
/// <summary>
/// 创建委托有返回值的表达式p=>p.propertyName
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="sort"></param>
/// <returns></returns>
public static Func<T, TKey> GetFun<T, TKey>(this string propertyName)
{
return propertyName.GetExpression<T, TKey>(typeof(T).GetExpressionParameter()).Compile();
}
/// <summary>
/// 创建lambda表达式p=>false
/// 在已知TKey字段类型时,如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID
/// Expression<Func<Out_Scheduling, DateTime>> expression = x => x.CreateDate;指定了类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, TKey>> GetExpression<T, TKey>(this string propertyName, ParameterExpression parameter)
{
if (typeof(TKey).Name == "Object")
return Expression.Lambda<Func<T, TKey>>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter);
return Expression.Lambda<Func<T, TKey>>(Expression.Property(parameter, propertyName), parameter);
}
/// <summary>
/// 创建lambda表达式p=>false
/// object不能确认字段类型(datetime,int,string),如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID
/// Expression<Func<Out_Scheduling, object>> expression = x => x.CreateDate;任意类型的字段
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, object>> GetExpression<T>(this string propertyName)
{
return propertyName.GetExpression<T, object>(typeof(T).GetExpressionParameter());
}
public static Expression<Func<T, object>> GetExpression<T>(this string propertyName, ParameterExpression parameter)
{
return Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName">字段名</param>
/// <param name="propertyValue">表达式的值</param>
/// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue
/// p=>p.propertyName.Contains(propertyValue)</param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateExpression<T>(this string propertyName, object propertyValue, LinqExpressionType expressionType)
{
return propertyName.CreateExpression<T>(propertyValue, null, expressionType);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName">字段名</param>
/// <param name="propertyValue">表达式的值</param>
/// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue
/// p=>p.propertyName.Contains(propertyValue)</param>
/// <returns></returns>
private static Expression<Func<T, bool>> CreateExpression<T>(
this string propertyName,
object propertyValue,
ParameterExpression parameter,
LinqExpressionType expressionType)
{
Type proType = typeof(T).GetProperty(propertyName).PropertyType;
//创建节点变量如p=>的节点p
// parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p
parameter = parameter ?? Expression.Parameter(typeof(T), "p");
//创建节点的属性p=>p.name 属性name
MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName);
if (expressionType == LinqExpressionType.In)
{
if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确");
bool isStringValue = true;
List<object> objList = new List<object>();
if (proType.ToString() != "System.String")
{
isStringValue = false;
foreach (var value in list)
{
objList.Add(value.ToString().ChangeType(proType));
}
list = objList;
}
if (isStringValue)
{
//string 类型的字段,如果值带有'单引号,EF会默认变成''两个单引号
MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains");
//创建集合常量并设置为常量的值
ConstantExpression constantCollection = Expression.Constant(list);
//创建一个表示调用带参数的方法的new string[]{"1","a"}.Contains("a");
MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty);
return Expression.Lambda<Func<T, bool>>(methodCall, parameter);
}
//非string字段按上面方式处理报异常Null TypeMapping in Sql Tree
BinaryExpression body = null;
foreach (var value in list)
{
ConstantExpression constantExpression = Expression.Constant(value);
UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type);
body = body == null
? Expression.Equal(unaryExpression, constantExpression)
: Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression));
}
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
// object value = propertyValue;
ConstantExpression constant = proType.ToString() == "System.String"
? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType));
UnaryExpression member = Expression.Convert(memberProperty, constant.Type);
Expression<Func<T, bool>> expression;
switch (expressionType)
{
//p=>p.propertyName == propertyValue
case LinqExpressionType.Equal:
expression = Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
break;
//p=>p.propertyName != propertyValue
case LinqExpressionType.NotEqual:
expression = Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
break;
// p => p.propertyName > propertyValue
case LinqExpressionType.GreaterThan:
expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
break;
// p => p.propertyName < propertyValue
case LinqExpressionType.LessThan:
expression = Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
break;
// p => p.propertyName >= propertyValue
case LinqExpressionType.ThanOrEqual:
expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
break;
// p => p.propertyName <= propertyValue
case LinqExpressionType.LessThanOrEqual:
expression = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
break;
// p => p.propertyName.Contains(propertyValue)
// p => !p.propertyName.Contains(propertyValue)
case LinqExpressionType.Contains:
case LinqExpressionType.NotContains:
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
constant = Expression.Constant(propertyValue, typeof(string));
if (expressionType == LinqExpressionType.Contains)
{
expression = Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
else
{
expression = Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
break;
default:
// p => p.false
expression = False<T>();
break;
}
return expression;
}
/// <summary>
/// 表达式转换成KeyValList(主要用于多字段排序,并且多个字段的排序规则不一样)
/// 如有多个字段进行排序,参数格式为
/// Expression<Func<Out_Scheduling, Dictionary<object, bool>>> orderBy = x => new Dictionary<object, bool>() {
/// { x.ID, true },
/// { x.DestWarehouseName, true }
/// };
/// 返回的是new Dictionary<object, bool>(){{}}key为排序字段bool为升降序
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="expression"></param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, QueryOrderBy>> GetExpressionToPair<T>(this Expression<Func<T, Dictionary<object, QueryOrderBy>>> expression)
{
foreach (var exp in ((ListInitExpression)expression.Body).Initializers)
{
yield return new KeyValuePair<string, QueryOrderBy>(
exp.Arguments[0] is MemberExpression ?
(exp.Arguments[0] as MemberExpression).Member.Name.ToString()
: ((exp.Arguments[0] as UnaryExpression).Operand as MemberExpression).Member.Name,
(QueryOrderBy)((exp.Arguments[1] as ConstantExpression).Value));
}
}
/// <summary>
/// 表达式转换成KeyValList(主要用于多字段排序,并且多个字段的排序规则不一样)
/// 如有多个字段进行排序,参数格式为
/// Expression<Func<Out_Scheduling, Dictionary<object, QueryOrderBy>>> orderBy = x => new Dictionary<object, QueryOrderBy>() {
/// { x.ID, QueryOrderBy.Desc },
/// { x.DestWarehouseName, QueryOrderBy.Asc }
/// };
/// 返回的是new Dictionary<object, QueryOrderBy>(){{}}key为排序字段QueryOrderBy为排序方式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="expression"></param>
/// <returns></returns>
public static Dictionary<string, QueryOrderBy> GetExpressionToDic<T>(this Expression<Func<T, Dictionary<object, QueryOrderBy>>> expression)
{
return expression.GetExpressionToPair().Reverse().ToList().ToDictionary(x => x.Key, x => x.Value);
}
/// <summary>
/// 解析多字段排序
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="queryable"></param>
/// <param name="orderBySelector">string=排序的字段,bool=true降序/false升序</param>
/// <returns></returns>
public static IQueryable<TEntity> GetIQueryableOrderBy<TEntity>(this IQueryable<TEntity> queryable, Dictionary<string, QueryOrderBy> orderBySelector)
{
string[] orderByKeys = orderBySelector.Select(x => x.Key).ToArray();
if (orderByKeys == null || orderByKeys.Length == 0) return queryable;
IOrderedQueryable<TEntity> queryableOrderBy = null;
// string orderByKey = orderByKeys[^1];
string orderByKey = orderByKeys[orderByKeys.Length-1];
queryableOrderBy = orderBySelector[orderByKey] == QueryOrderBy.Desc
? queryableOrderBy = queryable.OrderByDescending(orderByKey.GetExpression<TEntity>())
: queryable.OrderBy(orderByKey.GetExpression<TEntity>());
for (int i = orderByKeys.Length - 2; i >= 0; i--)
{
queryableOrderBy = orderBySelector[orderByKeys[i]] == QueryOrderBy.Desc
? queryableOrderBy.ThenByDescending(orderByKeys[i].GetExpression<TEntity>())
: queryableOrderBy.ThenBy(orderByKeys[i].GetExpression<TEntity>());
}
return queryableOrderBy;
}
/// <summary>
/// 获取对象表达式指定属性的值
/// 如获取:Out_Scheduling对象的ID或基他字段
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="expression">格式 Expression<Func<Out_Scheduling, object>>sch=x=>new {x.v1,x.v2} or x=>x.v1 解析里面的值返回为数组</param>
/// <returns></returns>
public static string[] GetExpressionToArray<TEntity>(this Expression<Func<TEntity, object>> expression)
{
string[] propertyNames = null;
if (expression.Body is MemberExpression)
{
propertyNames = new string[] { ((MemberExpression)expression.Body).Member.Name };
}
else
{
propertyNames = expression.GetExpressionProperty().Distinct().ToArray();
}
return propertyNames;
}
/// <summary>
/// 与下面and生成方式有所不同如果直接用表达式1.2进行合并产会提示数据源不同的异常只能使用下面的的and合并
/// 此种合并是在使用的同一个数据源(变量),生成的sql语句同样有性能问题(本身可以索引扫描的,生成的sql语句的case when变成索引查找)
/// <summary>
/// 通过字段动态生成where and /or表达
/// 如:有多个where条件当条件成立时where 1=1 and/or 2=2,依次往后拼接
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="listParas">ExpressionParameters
/// 1、Field生成的字段
/// 2、ExpressionType 表达式类型大于、小于、于大=、小于=、contains
/// 3、Value表达式的值
/// </param>
/// <returns></returns>
public static Expression<Func<T, bool>> And<T>(List<ExpressionParameters> listExpress)
{
return listExpress.Compose<T>(Expression.And);
}
/// <summary>
/// 同上面and用法相同
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="listExpress"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or<T>(this List<ExpressionParameters> listExpress)
{
return listExpress.Compose<T>(Expression.Or);
}
private static Expression<Func<T, bool>> Compose<T>(this List<ExpressionParameters> listExpress, Func<Expression, Expression, Expression> merge)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
Expression<Func<T, bool>> expression = null;
foreach (ExpressionParameters exp in listExpress)
{
if (expression == null)
{
expression = exp.Field.GetExpression<T, bool>(parameter);
}
else
{
expression = expression.Compose(exp.Field.GetExpression<T, bool>(parameter), merge);
}
}
return expression;
}
/// <summary>
/// https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/
/// 表达式合并(合并生产的sql语句有性能问题)
/// 合并两个where条件多个查询条件时判断条件成立才where
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="first"></param>
/// <param name="second"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.Or);
}
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// build parameter map (from parameters of second to parameters of first)
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with parameters from the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// apply composition of lambda expression bodies to parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
public static IQueryable<Result> GetQueryableSelect<Source, Result>(this IQueryable<Source> queryable)
{
Expression<Func<Source, Result>> expression = CreateMemberInitExpression<Source, Result>();
return queryable.Select(expression);
}
/// <summary>
/// 动态创建表达式Expression<Func<Animal, User>> expression = CreateMemberInitExpression<Animal, User>();
///结果为Expression<Func<Animal, User>> expression1 = x => new User() { Age = x.Age, Species = x.Species };
///参照文档https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.memberinitexpression?redirectedfrom=MSDN&view=netframework-4.8
/// </summary>
/// <typeparam name="Source"></typeparam>
/// <typeparam name="Result"></typeparam>
/// <returns></returns>
public static Expression<Func<Source, Result>> CreateMemberInitExpression<Source, Result>(Type resultType = null)
{
resultType = resultType ?? typeof(Result);
ParameterExpression left = Expression.Parameter(typeof(Source), "p");
NewExpression newExpression = Expression.New(resultType);
PropertyInfo[] propertyInfos = resultType.GetProperties();
List<MemberBinding> memberBindings = new List<MemberBinding>();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
MemberExpression member = Expression.Property(left, propertyInfo.Name);
MemberBinding speciesMemberBinding = Expression.Bind(resultType.GetMember(propertyInfo.Name)[0], member);
memberBindings.Add(speciesMemberBinding);
}
MemberInitExpression memberInitExpression = Expression.MemberInit(newExpression, memberBindings);
Expression<Func<Source, Result>> expression = Expression.Lambda<Func<Source, Result>>(memberInitExpression, new ParameterExpression[] { left });
return expression;
}
public static Expression<Func<Source, object>> CreateMemberInitExpression<Source>(Type resultType)
{
return CreateMemberInitExpression<Source, object>(resultType);
}
/// <summary>
/// 属性判断待完
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static IEnumerable<PropertyInfo> GetGenericProperties(this Type type)
{
return type.GetProperties().GetGenericProperties();
}
/// <summary>
/// 属性判断待完
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public static IEnumerable<PropertyInfo> GetGenericProperties(this IEnumerable<PropertyInfo> properties)
{
return properties.Where(x => !x.PropertyType.IsGenericType && x.PropertyType.GetInterface("IList") == null || x.PropertyType.GetInterface("IEnumerable", false) == null);
}
}
public class ExpressionParameters
{
public string Field { get; set; }
public LinqExpressionType ExpressionType { get; set; }
public object Value { get; set; }
// public
}
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Infrastructure.Extensions
{
public static class SecurityEncDecryptExtensions
{
private static byte[] Keys = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
/// <summary>
/// DES加密字符串
/// </summary>
/// <param name="encryptString">待加密的字符串</param>
/// <param name="encryptKey">加密密钥,要求为16位</param>
/// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
public static string EncryptDES(this string encryptString, string encryptKey)
{
try
{
byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 16));
byte[] rgbIV = Keys;
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
using (var DCSP = DES.Create())
{
using (MemoryStream mStream = new MemoryStream())
{
using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
{
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray()).Replace('+', '_').Replace('/', '~');
}
}
}
}
catch (Exception ex)
{
throw new Exception("密码加密异常" + ex.Message);
}
}
/// <summary>
/// DES解密字符串
/// </summary>
/// <param name="decryptString">待解密的字符串</param>
/// <param name="decryptKey">解密密钥,要求为16位,和加密密钥相同</param>
/// <returns>解密成功返回解密后的字符串,失败返源串</returns>
public static string DecryptDES(this string decryptString, string decryptKey)
{
byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 16));
byte[] rgbIV = Keys;
byte[] inputByteArray = Convert.FromBase64String(decryptString.Replace('_', '+').Replace('~', '/'));
using (var DCSP = DES.Create())
{
using (MemoryStream mStream = new MemoryStream())
{
using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write))
{
byte[] inputByteArrays = new byte[inputByteArray.Length];
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Encoding.UTF8.GetString(mStream.ToArray());
}
}
}
}
public static bool TryDecryptDES(this string decryptString, string decryptKey, out string result)
{
result = "";
try
{
result = DecryptDES(decryptString, decryptKey);
return true;
}
catch
{
return false;
}
}
}
}

View File

@ -0,0 +1,28 @@
using Infrastructure.Extensions.AutofacManager;
using Infrastructure.Provider;
namespace Infrastructure.Extensions
{
public static class ServerExtension
{
/// <summary>
/// 返回的路径后面不带/,拼接时需要自己加上/
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string MapPath(this string path)
{
return MapPath(path, false);
}
/// <summary>
///
/// </summary>
/// <param name="path"></param>
/// <param name="rootPath">获取wwwroot路径</param>
/// <returns></returns>
public static string MapPath(this string path,bool rootPath)
{
return AutofacContainerModule.GetService<IPathProvider>().MapPath(path,rootPath);
}
}
}

File diff suppressed because one or more lines are too long

25
Infrastructure/Filter.cs Normal file
View File

@ -0,0 +1,25 @@
namespace Infrastructure
{
public class Filter
{
public string Key { get; set; }
public string Value { get; set; }
public string Contrast { get; set; }
public string Text { get; set; }
}
public class FilterGroup
{
/// <summary>
/// or /and
/// </summary>
public string Operation { get; set; }
public Filter[] Filters { get; set; }
public FilterGroup[] Children { get; set; }
}
}

View File

@ -0,0 +1,126 @@
// ***********************************************************************
// Assembly : FairUtility
// Author : Yubao Li
// Created : 10-13-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 10-13-2015
// ***********************************************************************
// <copyright file="GenerateId.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary>创建唯一ID</summary>
// ***********************************************************************
using System;
using System.Security.Cryptography;
namespace Infrastructure
{
public class GenerateId
{
public static string GetGuidHash()
{
return Guid.NewGuid().ToString().GetHashCode().ToString("x");
}
/// <summary>
/// 生成一个长整型可以转成19字节长的字符串
/// </summary>
/// <returns>System.Int64.</returns>
public static long GenerateLong()
{
byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToInt64(buffer, 0);
}
/// <summary>
/// 生成16个字节长度的数据与英文组合串
/// </summary>
public static string GenerateStr()
{
long i = 1;
foreach (byte b in Guid.NewGuid().ToByteArray())
{
i *= ((int)b + 1);
}
return String.Format("{0:x}", i - DateTime.Now.Ticks);
}
/// <summary>
/// 创建11位的英文与数字组合
/// </summary>
/// <returns>System.String.</returns>
public static string ShortStr()
{
return Convert(GenerateLong());
}
/// <summary>
/// 唯一订单号生成
/// </summary>
/// <returns></returns>
public static string GenerateOrderNumber()
{
string strDateTimeNumber = DateTime.Now.ToString("yyyyMMddHHmmssffff");
string strRandomResult = NextRandom(1000, 1).ToString("0000");
return strDateTimeNumber + strRandomResult;
}
#region private
/// <summary>
/// 参考msdn上的RNGCryptoServiceProvider例子
/// </summary>
/// <param name="numSeeds"></param>
/// <param name="length"></param>
/// <returns></returns>
private static int NextRandom(int numSeeds, int length)
{
// Create a byte array to hold the random value.
byte[] randomNumber = new byte[length];
// Create a new instance of the RNGCryptoServiceProvider.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
// Fill the array with a random value.
rng.GetBytes(randomNumber);
// Convert the byte to an uint value to make the modulus operation easier.
uint randomResult = 0x0;
for (int i = 0; i < length; i++)
{
randomResult |= ((uint) randomNumber[i] << ((length - 1 - i)*8));
}
return (int) (randomResult%numSeeds) + 1;
}
static string Seq = "s9LFkgy5RovixI1aOf8UhdY3r4DMplQZJXPqebE0WSjBn7wVzmN2Gc6THCAKut";
/// <summary>
/// 10进制转换为62进制
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private static string Convert(long id)
{
if (id < 62)
{
return Seq[(int) id].ToString();
}
int y = (int) (id%62);
long x = (long) (id/62);
return Convert(x) + Seq[y];
}
#endregion
}
}

View File

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers
{
public class AESHelper
{
//
// 摘要:
// 32位处理key
//
// 参数:
// key:
// 原字节
private static string GetAesKey(string key)
{
int length = key.Length;
if (length < 32)
{
for (int i = 0; i < 32 - length; i++)
{
key += "0";
}
return key;
}
return key[..32];
}
//
// 摘要:
// 使用AES加密字符串
//
// 参数:
// content:
// 加密内容
//
// key:
// 秘钥
//
// vi:
// 偏移量
//
// 返回结果:
// Base64字符串结果
public static string AesEncrypt(string content, string key, string vi = "1234567890000000")
{
byte[] bytes = Encoding.UTF8.GetBytes(GetAesKey(key));
byte[] bytes2 = Encoding.UTF8.GetBytes(vi);
byte[] bytes3 = Encoding.UTF8.GetBytes(content);
SymmetricAlgorithm symmetricAlgorithm = Aes.Create();
symmetricAlgorithm.IV = bytes2;
symmetricAlgorithm.Key = bytes;
symmetricAlgorithm.Mode = CipherMode.CBC;
symmetricAlgorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform cryptoTransform = symmetricAlgorithm.CreateEncryptor();
byte[] inArray = cryptoTransform.TransformFinalBlock(bytes3, 0, bytes3.Length);
return Convert.ToBase64String(inArray);
}
//
// 摘要:
// 使用AES解密字符串
//
// 参数:
// content:
// 内容
//
// key:
// 秘钥
//
// vi:
// 偏移量
//
// 返回结果:
// UTF8解密结果
public static string AesDecrypt(string content, string key, string vi = "1234567890000000")
{
byte[] bytes = Encoding.UTF8.GetBytes(GetAesKey(key));
byte[] bytes2 = Encoding.UTF8.GetBytes(vi);
byte[] array = Convert.FromBase64String(content);
SymmetricAlgorithm symmetricAlgorithm = Aes.Create();
symmetricAlgorithm.IV = bytes2;
symmetricAlgorithm.Key = bytes;
symmetricAlgorithm.Mode = CipherMode.CBC;
symmetricAlgorithm.Padding = PaddingMode.PKCS7;
ICryptoTransform cryptoTransform = symmetricAlgorithm.CreateDecryptor();
byte[] bytes3 = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
return Encoding.UTF8.GetString(bytes3);
}
}
}

View File

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Infrastructure.Helpers
{
/// <summary>
/// 常用公共类
/// </summary>
public class CommonHelper
{
#region Stopwatch计时器
/// <summary>
/// 计时器开始
/// </summary>
/// <returns></returns>
public static Stopwatch TimerStart()
{
Stopwatch watch = new Stopwatch();
watch.Reset();
watch.Start();
return watch;
}
/// <summary>
/// 计时器结束
/// </summary>
/// <param name="watch"></param>
/// <returns></returns>
public static string TimerEnd(Stopwatch watch)
{
watch.Stop();
double costtime = watch.ElapsedMilliseconds;
return costtime.ToString();
}
#endregion
#region 删除数组中的重复项
/// <summary>
/// 删除数组中的重复项
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static string[] RemoveDup(string[] values)
{
List<string> list = new List<string>();
for (int i = 0; i < values.Length; i++)//遍历数组成员
{
if (!list.Contains(values[i]))
{
list.Add(values[i]);
};
}
return list.ToArray();
}
#endregion
#region 自动生成日期编号
/// <summary>
/// 自动生成编号 201008251145409865
/// </summary>
/// <returns></returns>
public static string CreateNo()
{
Random random = new Random();
string strRandom = random.Next(1000, 10000).ToString(); //生成编号
string code = DateTime.Now.ToString("yyyyMMddHHmmss") + strRandom;//形如
return code;
}
#endregion
#region 生成0-9随机数
/// <summary>
/// 生成0-9随机数
/// </summary>
/// <param name="codeNum">生成长度</param>
/// <returns></returns>
public static string RndNum(int codeNum)
{
StringBuilder sb = new StringBuilder(codeNum);
Random rand = new Random();
for (int i = 1; i < codeNum + 1; i++)
{
int t = rand.Next(9);
sb.AppendFormat("{0}", t);
}
return sb.ToString();
}
#endregion
#region 删除最后一个字符之后的字符
/// <summary>
/// 删除最后结尾的一个逗号
/// </summary>
public static string DelLastComma(string str)
{
return str.Substring(0, str.LastIndexOf(","));
}
/// <summary>
/// 删除最后结尾的指定字符后的字符
/// </summary>
public static string DelLastChar(string str, string strchar)
{
return str.Substring(0, str.LastIndexOf(strchar));
}
/// <summary>
/// 删除最后结尾的长度
/// </summary>
/// <param name="str"></param>
/// <param name="Length"></param>
/// <returns></returns>
public static string DelLastLength(string str, int Length)
{
if (string.IsNullOrEmpty(str))
return "";
str = str.Substring(0, str.Length - Length);
return str;
}
#endregion
}
}

View File

@ -0,0 +1,23 @@
using System;
using Enyim.Caching.Configuration;
using Microsoft.Extensions.Configuration;
namespace Infrastructure.Helpers
{
public class ConfigHelper
{
public static IConfigurationRoot GetConfigRoot()
{
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development"}.json",
optional: true)
.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
return configuration;
}
}
}

View File

@ -0,0 +1,42 @@
using System;
namespace Infrastructure.Helpers
{
public class DateTimeHelper
{
public static string FriendlyDate(DateTime? date)
{
if (!date.HasValue) return string.Empty;
string strDate = date.Value.ToString("yyyy-MM-dd");
string vDate = string.Empty;
if(DateTime.Now.ToString("yyyy-MM-dd")==strDate)
{
vDate = "今天";
}
else if (DateTime.Now.AddDays(1).ToString("yyyy-MM-dd") == strDate)
{
vDate = "明天";
}
else if (DateTime.Now.AddDays(2).ToString("yyyy-MM-dd") == strDate)
{
vDate = "后天";
}
else if (DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") == strDate)
{
vDate = "昨天";
}
else if (DateTime.Now.AddDays(2).ToString("yyyy-MM-dd") == strDate)
{
vDate = "前天";
}
else
{
vDate = strDate;
}
return vDate;
}
}
}

View File

@ -0,0 +1,122 @@
using Infrastructure.Helpers.Excel.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers.Excel
{
public class ExcelConfig
{
/// <summary>
/// 文件名
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 前景色
/// </summary>
public System.Drawing.Color ForeColor { get; set; }
/// <summary>
/// 背景色
/// </summary>
public System.Drawing.Color Background { get; set; }
private short _titlepoint;
/// <summary>
/// 标题字号
/// </summary>
public short TitlePoint
{
get
{
if (_titlepoint == 0)
{
return 20;
}
else
{
return _titlepoint;
}
}
set { _titlepoint = value; }
}
private short _headpoint;
/// <summary>
/// 列头字号
/// </summary>
public short HeadPoint
{
get
{
if (_headpoint == 0)
{
return 10;
}
else
{
return _headpoint;
}
}
set { _headpoint = value; }
}
/// <summary>
/// 标题高度
/// </summary>
public short TitleHeight { get; set; }
/// <summary>
/// 列标题高度
/// </summary>
public short HeadHeight { get; set; }
private string _titlefont;
/// <summary>
/// 标题字体
/// </summary>
public string TitleFont
{
get
{
if (_titlefont == null)
{
return "微软雅黑";
}
else
{
return _titlefont;
}
}
set { _titlefont = value; }
}
private string _headfont;
/// <summary>
/// 列头字体
/// </summary>
public string HeadFont
{
get
{
if (_headfont == null)
{
return "微软雅黑";
}
else
{
return _headfont;
}
}
set { _headfont = value; }
}
/// <summary>
/// 是否按内容长度来适应表格宽度
/// </summary>
public bool IsAllSizeColumn { get; set; }
/// <summary>
/// 列设置
/// </summary>
public List<ColumnModel> ColumnEntity { get; set; }
}
}

View File

@ -0,0 +1,505 @@
using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers.Excel
{
public class ExcelHelper
{
#region DataTable导出到Excel的MemoryStream
/// <summary>
/// DataTable导出到Excel的MemoryStream Export()
/// </summary>
/// <param name="dtSource">DataTable数据源</param>
/// <param name="excelConfig">导出设置包含文件名、标题、列设置</param>
public static MemoryStream ExportMemoryStream(DataTable dtSource, ExcelConfig excelConfig)
{
Dictionary<string, DataColumn> DataColumnMap = new Dictionary<string, DataColumn>();
//DataTable dt = dtSource.Clone();
//var columns = dt.Columns;
foreach (DataColumn column in dtSource.Columns)
{
bool v = excelConfig.ColumnEntity.Exists(t => t.Column == column.ColumnName);
if (v)
{
DataColumnMap.Add(column.ColumnName, column);
//dtSource.Columns.Remove(column.ColumnName);
}
/*else {
DataColumnMap.Add(column.ColumnName, column);
}*/
}
HSSFWorkbook workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet();
#region 右击文件 属性信息
{
DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation();
dsi.Company = "山东慧创信息科技有限公司";
workbook.DocumentSummaryInformation = dsi;
SummaryInformation si = PropertySetFactory.CreateSummaryInformation();
si.Title = "标题信息"; //填加xls文件标题信息
si.Subject = "主题信息";//填加文件主题信息
si.CreateDateTime = System.DateTime.Now;
workbook.SummaryInformation = si;
}
#endregion
#region 设置标题样式
ICellStyle headStyle = workbook.CreateCellStyle();
int[] arrColWidth = new int[excelConfig.ColumnEntity.Count];
string[] arrColName = new string[excelConfig.ColumnEntity.Count];//列名
ICellStyle[] arryColumStyle = new ICellStyle[excelConfig.ColumnEntity.Count];//样式表
headStyle.Alignment = HorizontalAlignment.Center; // ------------------
if (excelConfig.Background != new System.Drawing.Color())
{
if (excelConfig.Background != new System.Drawing.Color())
{
headStyle.FillPattern = FillPattern.SolidForeground;
headStyle.FillForegroundColor = GetXLColour(workbook, excelConfig.Background);
}
}
IFont font = workbook.CreateFont();
font.FontHeightInPoints = excelConfig.TitlePoint;
if (excelConfig.ForeColor != new System.Drawing.Color())
{
font.Color = GetXLColour(workbook, excelConfig.ForeColor);
}
font.IsBold = true;
headStyle.SetFont(font);
#endregion
#region 列头及样式
ICellStyle cHeadStyle = workbook.CreateCellStyle();
cHeadStyle.Alignment = HorizontalAlignment.Center; // ------------------
IFont cfont = workbook.CreateFont();
cfont.FontHeightInPoints = excelConfig.HeadPoint;
cHeadStyle.SetFont(cfont);
#endregion
#region 设置内容单元格样式
int colNum = 0;
foreach (var columnentity in excelConfig.ColumnEntity)
{
//DataColumn item = DataColumnMap[column.Column];
ICellStyle columnStyle = workbook.CreateCellStyle();
columnStyle.Alignment = HorizontalAlignment.Center;
//Encoding.GetEncoding(936)
arrColWidth[colNum] = Encoding.UTF8.GetBytes(columnentity.Column).Length;
arrColName[colNum] = columnentity.Column.ToString();
arrColName[colNum] = columnentity.ExcelColumn;
if (columnentity.Width != 0)
{
arrColWidth[colNum] = columnentity.Width;
}
if (columnentity.Background != new System.Drawing.Color())
{
if (columnentity.Background != new System.Drawing.Color())
{
columnStyle.FillPattern = FillPattern.SolidForeground;
columnStyle.FillForegroundColor = GetXLColour(workbook, columnentity.Background);
}
}
if (columnentity.Font != null || columnentity.Point != 0 || columnentity.ForeColor != new System.Drawing.Color())
{
IFont columnFont = workbook.CreateFont();
columnFont.FontHeightInPoints = 10;
if (columnentity.Font != null)
{
columnFont.FontName = columnentity.Font;
}
if (columnentity.Point != 0)
{
columnFont.FontHeightInPoints = columnentity.Point;
}
if (columnentity.ForeColor != new System.Drawing.Color())
{
columnFont.Color = GetXLColour(workbook, columnentity.ForeColor);
}
columnStyle.SetFont(font);
}
columnStyle.Alignment = getAlignment(columnentity.Alignment);
arryColumStyle[colNum] = columnStyle;
colNum++;
}
if (excelConfig.IsAllSizeColumn)
{
#region 根据列中最长列的长度取得列宽
for (int i = 0; i < dtSource.Rows.Count; i++)
{
for (int j = 0; j < excelConfig.ColumnEntity.Count; j++)
{
if (arrColWidth[j] != 0)
{
//Encoding.GetEncoding(936)
int intTemp = Encoding.UTF8.GetBytes(dtSource.Rows[i][excelConfig.ColumnEntity[j].Column].ToString()).Length;
if (intTemp > arrColWidth[j])
{
arrColWidth[j] = intTemp;
}
}
}
}
#endregion
}
#endregion
int rowIndex = 0;
#region 表头及样式
if (excelConfig.Title != null)
{
IRow headerRow = sheet.CreateRow(rowIndex);
rowIndex++;
if (excelConfig.TitleHeight != 0)
{
headerRow.Height = (short)(excelConfig.TitleHeight * 20);
}
headerRow.HeightInPoints = 25;
headerRow.CreateCell(0).SetCellValue(excelConfig.Title);
headerRow.GetCell(0).CellStyle = headStyle;
if (excelConfig.ColumnEntity.Count > 1)
{
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, excelConfig.ColumnEntity.Count - 1)); // ------------------
}
}
#endregion
#region 列头及样式
{
IRow headerRow = sheet.CreateRow(rowIndex);
rowIndex++;
colNum = 0;
#region 如果设置了列标题就按列标题定义列头,没定义直接按字段名输出
foreach (var column in excelConfig.ColumnEntity)
{
headerRow.CreateCell(colNum).SetCellValue(arrColName[colNum]);
headerRow.GetCell(colNum).CellStyle = cHeadStyle;
//设置列宽
//sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);
int colWidth = (arrColWidth[colNum] + 1) * 256;
if (colWidth < 255 * 256)
{
sheet.SetColumnWidth(colNum, colWidth < 3000 ? 3000 : colWidth);
}
else
{
sheet.SetColumnWidth(colNum, 6000);
}
colNum++;
}
#endregion
}
#endregion
ICellStyle dateStyle = workbook.CreateCellStyle();
IDataFormat format = workbook.CreateDataFormat();
dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");
Dictionary<string, ICellStyle> dateStyleMap = new Dictionary<string, ICellStyle>();
dateStyleMap.Add("yyyy-mm-dd", dateStyle);
foreach (DataRow row in dtSource.Rows)
{
#region 新建表,填充表头,填充列头,样式
if (rowIndex == 65535)
{
sheet = workbook.CreateSheet();
rowIndex = 0;
#region 表头及样式
{
if (excelConfig.Title != null)
{
IRow headerRow = sheet.CreateRow(rowIndex);
rowIndex++;
if (excelConfig.TitleHeight != 0)
{
headerRow.Height = (short)(excelConfig.TitleHeight * 20);
}
headerRow.HeightInPoints = 25;
headerRow.CreateCell(0).SetCellValue(excelConfig.Title);
headerRow.GetCell(0).CellStyle = headStyle;
sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, excelConfig.ColumnEntity.Count - 1)); // ------------------
}
}
#endregion
#region 列头及样式
{
IRow headerRow = sheet.CreateRow(rowIndex);
rowIndex++;
#region 如果设置了列标题就按列标题定义列头,没定义直接按字段名输出
colNum = 0;
foreach (var column in excelConfig.ColumnEntity)
{
headerRow.CreateCell(colNum).SetCellValue(arrColName[colNum]);
headerRow.GetCell(colNum).CellStyle = cHeadStyle;
//设置列宽
sheet.SetColumnWidth(colNum, (arrColWidth[colNum] + 1) * 256);
colNum++;
}
#endregion
}
#endregion
}
#endregion
#region 填充内容
IRow dataRow = sheet.CreateRow(rowIndex);
colNum = 0;
foreach (var columnentity in excelConfig.ColumnEntity)
{
ICell newCell = dataRow.CreateCell(colNum);
newCell.CellStyle = arryColumStyle[colNum];
string drValue = row[columnentity.Column].ToString();
//ColumnModel columnentity = excelConfig.ColumnEntity.Find(t => t.Column == column.ColumnName);
if (!string.IsNullOrEmpty(columnentity.DateFormat))
{
if (!dateStyleMap.ContainsKey(columnentity.DateFormat))
{
ICellStyle dateStyle2 = workbook.CreateCellStyle();
IDataFormat format2 = workbook.CreateDataFormat();
dateStyle2.DataFormat = format.GetFormat(columnentity.DateFormat);
dateStyleMap.Add(columnentity.DateFormat, dateStyle2);
}
SetCell(newCell, dateStyleMap[columnentity.DateFormat], DataColumnMap[columnentity.Column].DataType, drValue);
}
else
{
SetCell(newCell, dateStyle, DataColumnMap[columnentity.Column].DataType, drValue);
}
colNum++;
}
#endregion
rowIndex++;
}
MemoryStream ms = new MemoryStream();
workbook.Write(ms);
ms.Flush();
ms.Position = 0;
return ms;
}
#endregion
#region 设置表格内容
private static void SetCell(ICell newCell, ICellStyle dateStyle, Type dataType, string drValue)
{
switch (dataType.ToString())
{
case "System.String"://字符串类型
newCell.SetCellValue(drValue);
break;
case "System.DateTime"://日期类型
System.DateTime dateV;
if (System.DateTime.TryParse(drValue, out dateV))
{
newCell.SetCellValue(dateV);
}
else
{
newCell.SetCellValue("");
}
newCell.CellStyle = dateStyle;//格式化显示
break;
case "System.Boolean"://布尔型
bool boolV = false;
bool.TryParse(drValue, out boolV);
newCell.SetCellValue(boolV);
break;
case "System.Int16"://整型
case "System.Int32":
case "System.Int64":
case "System.Byte":
int intV = 0;
int.TryParse(drValue, out intV);
newCell.SetCellValue(intV);
break;
case "System.Decimal"://浮点型
case "System.Double":
double doubV = 0;
double.TryParse(drValue, out doubV);
newCell.SetCellValue(doubV);
break;
case "System.DBNull"://空值处理
newCell.SetCellValue("");
break;
default:
newCell.SetCellValue("");
break;
}
}
#endregion
#region 从Excel导入
/// <summary>
/// 读取excel ,默认第一行为标头
/// </summary>
/// <param name="strFileName">excel文档路径</param>
/// <returns></returns>
public static DataTable ExcelImport(string strFileName)
{
DataTable dt = new DataTable();
ISheet sheet = null;
using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
{
if (strFileName.IndexOf(".xlsx") == -1)//2003
{
HSSFWorkbook hssfworkbook = new HSSFWorkbook(file);
sheet = hssfworkbook.GetSheetAt(0);
}
else//2007
{
XSSFWorkbook xssfworkbook = new XSSFWorkbook(file);
sheet = xssfworkbook.GetSheetAt(0);
}
}
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
IRow headerRow = sheet.GetRow(0);
int cellCount = headerRow.LastCellNum;
for (int j = 0; j < cellCount; j++)
{
ICell cell = headerRow.GetCell(j);
dt.Columns.Add(cell.ToString());
}
for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
DataRow dataRow = dt.NewRow();
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
dataRow[j] = row.GetCell(j).ToString();
}
dt.Rows.Add(dataRow);
}
return dt;
}
/// <summary>
/// 读取excel ,默认第一行为标头
/// </summary>
/// <param name="fileStream">文件数据流</param>
/// <param name="flieType">文件类型</param>
/// <returns></returns>
public static DataTable ExcelImport(Stream fileStream, string flieType)
{
DataTable dt = new DataTable();
ISheet sheet = null;
if (flieType == ".xls")
{
HSSFWorkbook hssfworkbook = new HSSFWorkbook(fileStream);
sheet = hssfworkbook.GetSheetAt(0);
}
else
{
XSSFWorkbook xssfworkbook = new XSSFWorkbook(fileStream);
sheet = xssfworkbook.GetSheetAt(0);
}
System.Collections.IEnumerator rows = sheet.GetRowEnumerator();
IRow headerRow = sheet.GetRow(0);
int cellCount = headerRow.LastCellNum;
for (int j = 0; j < cellCount; j++)
{
ICell cell = headerRow.GetCell(j);
dt.Columns.Add(cell.ToString());
}
for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
DataRow dataRow = dt.NewRow();
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
dataRow[j] = row.GetCell(j).ToString();
}
dt.Rows.Add(dataRow);
}
return dt;
}
#endregion
#region RGB颜色转NPOI颜色
private static short GetXLColour(HSSFWorkbook workbook, System.Drawing.Color SystemColour)
{
short s = 0;
HSSFPalette XlPalette = workbook.GetCustomPalette();
NPOI.HSSF.Util.HSSFColor XlColour = XlPalette.FindColor(SystemColour.R, SystemColour.G, SystemColour.B);
if (XlColour == null)
{
if (NPOI.HSSF.Record.PaletteRecord.STANDARD_PALETTE_SIZE < 255)
{
XlColour = XlPalette.FindSimilarColor(SystemColour.R, SystemColour.G, SystemColour.B);
s = XlColour.Indexed;
}
}
else
s = XlColour.Indexed;
return s;
}
#endregion
#region 设置列的对齐方式
/// <summary>
/// 设置对齐方式
/// </summary>
/// <param name="style"></param>
/// <returns></returns>
private static HorizontalAlignment getAlignment(string style)
{
switch (style)
{
case "center":
return HorizontalAlignment.Center;
case "left":
return HorizontalAlignment.Left;
case "right":
return HorizontalAlignment.Right;
case "fill":
return HorizontalAlignment.Fill;
case "justify":
return HorizontalAlignment.Justify;
case "centerselection":
return HorizontalAlignment.CenterSelection;
case "distributed":
return HorizontalAlignment.Distributed;
}
return NPOI.SS.UserModel.HorizontalAlignment.General;
}
#endregion
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers.Excel.Model
{
public class ColumnModel
{
/// <summary>
/// 列名
/// </summary>
public string Column { get; set; }
/// <summary>
/// Excel列名
/// </summary>
public string ExcelColumn { get; set; }
/// <summary>
/// 宽度
/// </summary>
public int Width { get; set; }
/// <summary>
/// 前景色
/// </summary>
public System.Drawing.Color ForeColor { get; set; }
/// <summary>
/// 背景色
/// </summary>
public System.Drawing.Color Background { get; set; }
/// <summary>
/// 字体
/// </summary>
public string Font { get; set; }
/// <summary>
/// 字号
/// </summary>
public short Point { get; set; }
/// <summary>
///对齐方式
///left 左
///center 中间
///right 右
///fill 填充
///justify 两端对齐
///centerselection 跨行居中
///distributed
/// </summary>
public string Alignment { get; set; }
/// <summary>
/// 时间格式化
/// </summary>
public string DateFormat { get; set; }
}
}

View File

@ -0,0 +1,407 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Infrastructure.Extensions;
namespace Infrastructure.Helpers
{
public class FileHelper
{
private static object _filePathObj = new object();
/// <summary>
/// 通过迭代器读取平面文件行内容(必须是带有\r\n换行的文件,百万行以上的内容读取效率存在问题,适用于100M左右文件行100W内超出的会有卡顿)
/// </summary>
/// <param name="fullPath">文件全路径</param>
/// <param name="page">分页页数</param>
/// <param name="pageSize">分页大小</param>
/// <param name="seekEnd"> 是否最后一行向前读取,默认从前向后读取</param>
/// <returns></returns>
public static IEnumerable<string> ReadPageLine(string fullPath, int page, int pageSize, bool seekEnd = false)
{
if (page <= 0)
{
page = 1;
}
fullPath = StringExtension.ReplacePath(fullPath);
var lines = File.ReadLines(fullPath, Encoding.UTF8);
if (seekEnd)
{
int lineCount = lines.Count();
int linPageCount = (int)Math.Ceiling(lineCount / (pageSize * 1.00));
//超过总页数,不处理
if (page > linPageCount)
{
page = 0;
pageSize = 0;
}
else if (page == linPageCount)//最后一页,取最后一页剩下所有的行
{
pageSize = lineCount - (page - 1) * pageSize;
if (page == 1)
{
page = 0;
}
else
{
page = lines.Count() - page * pageSize;
}
}
else
{
page = lines.Count() - page * pageSize;
}
}
else
{
page = (page - 1) * pageSize;
}
lines = lines.Skip(page).Take(pageSize);
var enumerator = lines.GetEnumerator();
int count = 1;
while (enumerator.MoveNext() || count <= pageSize)
{
yield return enumerator.Current;
count++;
}
enumerator.Dispose();
}
public static bool FileExists(string path)
{
return File.Exists(StringExtension.ReplacePath(path));
}
public static string GetCurrentDownLoadPath()
{
return ("Download\\").MapPath();
}
public static bool DirectoryExists(string path)
{
return Directory.Exists(StringExtension.ReplacePath(path));
}
public static string Read_File(string fullpath, string filename, string suffix)
{
return ReadFile((fullpath + "\\" + filename + suffix).MapPath());
}
public static string ReadFile(string fullName)
{
// Encoding code = Encoding.GetEncoding(); //Encoding.GetEncoding("gb2312");
string temp = fullName.MapPath().ReplacePath();
string str = "";
if (!File.Exists(temp))
{
return str;
}
StreamReader sr = null;
try
{
sr = new StreamReader(temp);
str = sr.ReadToEnd(); // 读取文件
}
catch { }
sr?.Close();
sr?.Dispose();
return str;
}
/// <summary>
/// 取后缀名
/// </summary>
/// <param name="filename">文件名</param>
/// <returns>.gif|.html格式</returns>
public static string GetPostfixStr(string filename)
{
int start = filename.LastIndexOf(".");
int length = filename.Length;
string postfix = filename.Substring(start, length - start);
return postfix;
}
/// <summary>
///
/// </summary>
/// <param name="path">路径 </param>
/// <param name="fileName">文件名</param>
/// <param name="content">写入的内容</param>
/// <param name="appendToLast">是否将内容添加到未尾,默认不添加</param>
public static void WriteFile(string path, string fileName, string content, bool appendToLast = false)
{
path = StringExtension.ReplacePath(path);
fileName = StringExtension.ReplacePath(fileName);
if (!Directory.Exists(path))//如果不存在就创建file文件夹
Directory.CreateDirectory(path);
using (FileStream stream = File.Open(Path.Combine(path, fileName), FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] by = Encoding.Default.GetBytes(content);
if (appendToLast)
{
stream.Position = stream.Length;
}
else
{
stream.SetLength(0);
}
stream.Write(by, 0, by.Length);
}
}
/// <summary>
/// 追加文件
/// </summary>
/// <param name="Path">文件路径</param>
/// <param name="strings">内容</param>
public static void FileAdd(string Path, string strings)
{
StreamWriter sw = File.AppendText(StringExtension.ReplacePath(Path));
sw.Write(strings);
sw.Flush();
sw.Close();
sw.Dispose();
}
/// <summary>
/// 拷贝文件
/// </summary>
/// <param name="OrignFile">原始文件</param>
/// <param name="NewFile">新文件路径</param>
public static void FileCoppy(string OrignFile, string NewFile)
{
File.Copy(StringExtension.ReplacePath(OrignFile), StringExtension.ReplacePath(NewFile), true);
}
/// <summary>
/// 删除文件
/// </summary>
/// <param name="Path">路径</param>
public static void FileDel(string Path)
{
File.Delete(StringExtension.ReplacePath(Path));
}
/// <summary>
/// 移动文件
/// </summary>
/// <param name="OrignFile">原始路径</param>
/// <param name="NewFile">新路径</param>
public static void FileMove(string OrignFile, string NewFile)
{
File.Move(StringExtension.ReplacePath(OrignFile), StringExtension.ReplacePath(NewFile));
}
/// <summary>
/// 在当前目录下创建目录
/// </summary>
/// <param name="OrignFolder">当前目录</param>
/// <param name="NewFloder">新目录</param>
public static void FolderCreate(string OrignFolder, string NewFloder)
{
Directory.SetCurrentDirectory(StringExtension.ReplacePath(OrignFolder));
Directory.CreateDirectory(StringExtension.ReplacePath(NewFloder));
}
/// <summary>
/// 创建文件夹
/// </summary>
/// <param name="Path"></param>
public static void FolderCreate(string Path)
{
// 判断目标目录是否存在如果不存在则新建之
if (!Directory.Exists(StringExtension.ReplacePath(Path)))
Directory.CreateDirectory(StringExtension.ReplacePath(Path));
}
public static void FileCreate(string Path)
{
FileInfo CreateFile = new FileInfo(StringExtension.ReplacePath(Path)); //创建文件
if (!CreateFile.Exists)
{
FileStream FS = CreateFile.Create();
FS.Close();
}
}
/// <summary>
/// 递归删除文件夹目录及文件
/// </summary>
/// <param name="dir"></param>
/// <returns></returns>
public static void DeleteFolder(string dir)
{
dir = StringExtension.ReplacePath(dir);
if (Directory.Exists(dir)) //如果存在这个文件夹删除之
{
foreach (string d in Directory.GetFileSystemEntries(dir))
{
if (File.Exists(d))
File.Delete(d); //直接删除其中的文件
else
DeleteFolder(d); //递归删除子文件夹
}
Directory.Delete(dir, true); //删除已空文件夹
}
}
/// <summary>
/// 指定文件夹下面的所有内容copy到目标文件夹下面
/// </summary>
/// <param name="srcPath">原始路径</param>
/// <param name="aimPath">目标文件夹</param>
public static void CopyDir(string srcPath, string aimPath)
{
try
{
aimPath = StringExtension.ReplacePath(aimPath);
// 检查目标目录是否以目录分割字符结束如果不是则添加之
if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar)
aimPath += Path.DirectorySeparatorChar;
// 判断目标目录是否存在如果不存在则新建之
if (!Directory.Exists(aimPath))
Directory.CreateDirectory(aimPath);
// 得到源目录的文件列表,该里面是包含文件以及目录路径的一个数组
//如果你指向copy目标文件下面的文件而不包含目录请使用下面的方法
//string[] fileList = Directory.GetFiles(srcPath);
string[] fileList = Directory.GetFileSystemEntries(StringExtension.ReplacePath(srcPath));
//遍历所有的文件和目录
foreach (string file in fileList)
{
//先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
if (Directory.Exists(file))
CopyDir(file, aimPath + Path.GetFileName(file));
//否则直接Copy文件
else
File.Copy(file, aimPath + Path.GetFileName(file), true);
}
}
catch (Exception ee)
{
throw new Exception(ee.ToString());
}
}
/// <summary>
/// 获取文件夹大小
/// </summary>
/// <param name="dirPath">文件夹路径</param>
/// <returns></returns>
public static long GetDirectoryLength(string dirPath)
{
dirPath = StringExtension.ReplacePath(dirPath);
if (!Directory.Exists(dirPath))
return 0;
long len = 0;
DirectoryInfo di = new DirectoryInfo(dirPath);
foreach (FileInfo fi in di.GetFiles())
{
len += fi.Length;
}
DirectoryInfo[] dis = di.GetDirectories();
if (dis.Length > 0)
{
for (int i = 0; i < dis.Length; i++)
{
len += GetDirectoryLength(dis[i].FullName);
}
}
return len;
}
/// <summary>
/// 获取指定文件详细属性
/// </summary>
/// <param name="filePath">文件详细路径</param>
/// <returns></returns>
public static string GetFileAttibe(string filePath)
{
string str = "";
filePath = StringExtension.ReplacePath(filePath);
System.IO.FileInfo objFI = new System.IO.FileInfo(filePath);
str += "详细路径:" + objFI.FullName + "<br>文件名称:" + objFI.Name + "<br>文件长度:" + objFI.Length.ToString() + "字节<br>创建时间" + objFI.CreationTime.ToString() + "<br>最后访问时间:" + objFI.LastAccessTime.ToString() + "<br>修改时间:" + objFI.LastWriteTime.ToString() + "<br>所在目录:" + objFI.DirectoryName + "<br>扩展名:" + objFI.Extension;
return str;
}
/// <summary>
/// 括号匹配算法
/// </summary>
/// <param name="dataStr">原始字符串</param>
/// <param name="leftCode">左匹配符号</param>
/// <param name="rightCode">右匹配符号</param>
/// <returns></returns>
private static string parenthesisMatch(string dataStr, char leftCode, char rightCode)
{
Stack stack = new Stack();
string cut_text = "";
for (int i = 0; i < dataStr.Length; ++i)
{
char ch = dataStr[i];
if (stack.Count > 0)
{
cut_text += ch;
}
if (ch == leftCode)
{
stack.Push(ch);
}
if (ch == rightCode)
{
stack.Pop();
if (0 == stack.Count)
{
return cut_text.Substring(0, cut_text.Length - 1);
}
}
}
return "";
}
/// <summary>
/// 替换内容(正则 + 括号匹配算法)
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="addStr">追加内容</param>
public static void RegxAddContentByParenthesis(string path, string addStr)
{
path = StringExtension.ReplacePath(path);
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
string originStr = sr.ReadToEnd();
string pattern = @"DbContext\s*?({.*)";
if (Regex.IsMatch(originStr, pattern))
{
Match match = Regex.Match(originStr, pattern, RegexOptions.Singleline);
string cut_str = parenthesisMatch(match.Groups[1].Value, '{', '}'); // 剪切内容(原内容)
string new_str = cut_str + "\r\n " + addStr + "\r\n"; // 实际更新内容
originStr = originStr.Replace(cut_str, new_str);
}
sr.Close();
fs.Close();
FileStream fs2 = new FileStream(path, FileMode.Open, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs2);
sw.WriteLine(originStr);
sw.Close();
fs2.Close();
}
}
}

View File

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Infrastructure.Helpers
{
/// <summary>
/// List转成Tree
/// <para>李玉宝新增于2016-10-09 19:54:07</para>
/// </summary>
public static class GenericHelpers
{
/// <summary>
/// Generates tree of items from item list
/// </summary>
///
/// <typeparam name="T">Type of item in collection</typeparam>
/// <typeparam name="K">Type of parent_id</typeparam>
///
/// <param name="collection">Collection of items</param>
/// <param name="idSelector">Function extracting item's id</param>
/// <param name="parentIdSelector">Function extracting item's parent_id</param>
/// <param name="rootId">Root element id</param>
///
/// <returns>Tree of items</returns>
public static IEnumerable<TreeItem<T>> GenerateTree<T, K>(
this IEnumerable<T> collection,
Func<T, K> idSelector,
Func<T, K> parentIdSelector,
K rootId = default(K))
{
foreach (var c in collection.Where(u =>
{
var selector = parentIdSelector(u);
return (rootId == null && selector == null)
|| (rootId != null && rootId.Equals(selector));
}))
{
yield return new TreeItem<T>
{
Item = c,
Children = collection.GenerateTree(idSelector, parentIdSelector, idSelector(c))
};
}
}
/// <summary>
/// 把数组转为逗号连接的字符串
/// </summary>
/// <param name="data"></param>
/// <param name="Str"></param>
/// <returns></returns>
public static string ArrayToString(dynamic data, string Str)
{
string resStr = Str;
foreach (var item in data)
{
if (resStr != "")
{
resStr += ",";
}
if (item is string)
{
resStr += item;
}
else
{
resStr += item.Value;
}
}
return resStr;
}
}
}

View File

@ -0,0 +1,478 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Infrastructure.Helpers
{
public class HIKOpenAPI
{
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <param name="api"></param>
/// <param name="body"></param>
/// <param name="ak"></param>
/// <param name="sk"></param>
/// <returns></returns>
public static string HttpPost(string url, string api, string body, string ak, string sk)
{
var headers = new Dictionary<string, string> { { "Accept", "*/*" }, { "Content-Type", "application/json" } };
var request = new Request(Method.POST_STRING, url, api, ak, sk, 10000)
{
Headers = headers,
SignHeaderPrefixList = null,
Querys = null,
StringBody = body
};
var result = DoPoststring(request.Host, request.Path, request.Timeout, request.Headers, request.Querys, request.StringBody, request.SignHeaderPrefixList, request.AppKey, request.AppSecret, false);
return result;
}
//Post请求方法
public static string DoPoststring(string host, string path, int connectTimeout, Dictionary<string, string> headers,
Dictionary<string, string> querys, string body, List<string> signHeaderPrefixList, string appKey,
string appSecret, bool autoDown)
{
try
{
headers = initialBasicHeader("POST", path, headers, querys, null, signHeaderPrefixList, appKey,
appSecret);
ServicePointManager.ServerCertificateValidationCallback =
RemoteCertificateValidate;
//验证服务器证书回调自动验证
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 |
// SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(initUrl(host, path, querys));
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
//设置HTTP协议的并发连接数
//ServicePointManager.DefaultConnectionLimit = 512;
//关闭重定向
request.AllowAutoRedirect = true;
request.Method = "POST";
request.Timeout = connectTimeout;
string accept = headers["Accept"];
request.Accept = accept;
string contentType = headers["Content-Type"];
request.ContentType = contentType;
foreach (string headerKey in headers.Keys)
{
if (headerKey.Contains("x-ca-"))
{
request.Headers.Add(headerKey + ":" +
(string.IsNullOrWhiteSpace(headers[headerKey]) ? "" : headers[headerKey]));
}
if (headerKey.Equals("tagId"))
{
request.Headers.Add(headerKey + ":" +
(string.IsNullOrWhiteSpace(headers[headerKey]) ? "" : headers[headerKey]));
}
}
if (!string.IsNullOrWhiteSpace(body))
{
byte[] postBytes = Encoding.UTF8.GetBytes(body);
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
}
var response = (HttpWebResponse)request.GetResponse();
var result = "";
if (response.StatusCode != HttpStatusCode.OK) return result;
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
result = rdr.ReadToEnd();
}
return result;
}
catch (Exception ex)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(new { code = "404", msg = ex.Message });
}
}
//获取当时时间戳
public static long GetTimestamp(DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位
return t;
}
private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain,
SslPolicyErrors error)
{
//为了通过证书验证总是返回true
return true;
}
public static Dictionary<string, string> initialBasicHeader(string method, string path,
Dictionary<string, string> headers, Dictionary<string, string> querys, Dictionary<string, string> bodys,
List<string> signHeaderPrefixList, string appKey, string appSecret) //throws MalformedURLException
{
if (headers == null)
{
headers = new Dictionary<string, string>();
}
headers["x-ca-timestamp"] = GetTimestamp(DateTime.Now).ToString();
headers["x-ca-nonce"] = System.Guid.NewGuid().ToString();
headers["x-ca-key"] = appKey;
headers["x-ca-signature"] = sign(appSecret, method, path, headers, querys, bodys, signHeaderPrefixList);
return headers;
//https://223.99.16.253:6114/pic?
//5d00=a202l94-do7b18*35d69188-64fbf0ebc**561===sp**715=7t7662209067=1l3*1513o6*720-=46fe44pi1e9o=0-9e00b0
//&AccessKeyId=Qrq2LsyWF6GSM0zm&Expires=1677046120&Signature=Bw7dKuV6CX7w3ev56u6jBwRuGwU=
}
public static string initUrl(string host, string path, Dictionary<string, string> querys)
//throws UnsupportedEncodingException
{
StringBuilder sbUrl = new StringBuilder();
sbUrl.Append(host);
if (!string.IsNullOrWhiteSpace(path))
{
sbUrl.Append(path);
}
if (null != querys)
{
StringBuilder sbQuery = new StringBuilder();
foreach (string queryKey in querys.Keys)
{
if (0 < sbQuery.Length)
{
sbQuery.Append("&");
}
if (string.IsNullOrWhiteSpace(queryKey) && !string.IsNullOrWhiteSpace(querys[queryKey]))
{
sbQuery.Append(querys[queryKey]);
}
if (!string.IsNullOrWhiteSpace(queryKey))
{
sbQuery.Append(queryKey);
if (!string.IsNullOrWhiteSpace(querys[queryKey]))
{
sbQuery.Append("=").Append(HttpUtility.UrlEncode(querys[queryKey], Encoding.UTF8));
}
}
}
if (0 < sbQuery.Length)
{
sbUrl.Append("?").Append(sbQuery);
}
}
return sbUrl.ToString();
}
public static string sign(string secret, string method, string path, Dictionary<string, string> headers,
Dictionary<string, string> querys, Dictionary<string, string> bodys, List<string> signHeaderPrefixList)
{
try
{
//return HmacSHA256(buildstringToSign(method, path, headers, querys, bodys, signHeaderPrefixList), secret);
/*---message里的内容---*/
//POST
//*/*
//application/json
//x-ca-key:23125513
//x-ca-nonce:12d28d90-a7c3-45cc-ae6a-0cc8d5e22118
//x-ca-timestamp:1544495633599
//artemis/api/resource/v1/org/advance/orgList
string message = buildstringToSign(method, path, headers, querys, bodys, signHeaderPrefixList);
return HmacSHA256(message, secret);
}
catch (Exception ex)
{
return ex.Message;
}
}
public static string buildstringToSign(string method, string path, Dictionary<string, string> headers,
Dictionary<string, string> querys, Dictionary<string, string> bodys, List<string> signHeaderPrefixList)
{
StringBuilder sb = new StringBuilder();
sb.Append(method.ToUpper()).Append("\n");
if (null != headers)
{
if (null != headers["Accept"])
{
sb.Append((string)headers["Accept"]);
sb.Append("\n");
}
if (headers.Keys.Contains("Content-MD5") && null != headers["Content-MD5"])
{
sb.Append((string)headers["Content-MD5"]);
sb.Append("\n");
}
if (null != headers["Content-Type"])
{
sb.Append((string)headers["Content-Type"]);
sb.Append("\n");
}
if (headers.Keys.Contains("Date") && null != headers["Date"])
{
sb.Append((string)headers["Date"]);
sb.Append("\n");
}
}
sb.Append(buildHeaders(headers, signHeaderPrefixList));
sb.Append(buildResource(path, querys, bodys));
return sb.ToString();
}
public static string buildHeaders(Dictionary<string, string> headers, List<string> signHeaderPrefixList)
{
StringBuilder sb = new StringBuilder();
if (null != signHeaderPrefixList)
{
signHeaderPrefixList.Remove("x-ca-signature");
signHeaderPrefixList.Remove("Accept");
signHeaderPrefixList.Remove("Content-MD5");
signHeaderPrefixList.Remove("Content-Type");
signHeaderPrefixList.Remove("Date");
signHeaderPrefixList.Sort();
}
if (null != headers)
{
Dictionary<string, string> sortDictionary = new Dictionary<string, string>();
sortDictionary = headers;
//按key值升序排序
var dicSort = from objDic in sortDictionary orderby objDic.Key ascending select objDic;
StringBuilder signHeadersStringBuilder = new StringBuilder();
foreach (KeyValuePair<string, string> kvp in dicSort)
{
if (kvp.Key.Replace(" ", "").Contains("x-ca-"))
{
sb.Append(kvp.Key + ":");
if (!string.IsNullOrWhiteSpace(kvp.Value))
{
sb.Append(kvp.Value);
}
sb.Append("\n");
if (signHeadersStringBuilder.Length > 0)
{
signHeadersStringBuilder.Append(",");
}
signHeadersStringBuilder.Append(kvp.Key);
}
}
headers.Add("x-ca-signature-headers", signHeadersStringBuilder.ToString());
}
//x-ca-key:23125513
//x-ca-nonce:12d28d90-a7c3-45cc-ae6a-0cc8d5e22118
//x-ca-timestamp:1544495633599
return sb.ToString();
}
public static string buildResource(string path, Dictionary<string, string> querys, Dictionary<string, string> bodys)
{
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrWhiteSpace(path))
{
sb.Append(path);
}
Dictionary<string, string> sortDictionary = new Dictionary<string, string>();
if (querys != null)
{
//按key值升序排序
var dicSort = from objDic in querys orderby objDic.Key ascending select objDic;
foreach (KeyValuePair<string, string> kvp in dicSort)
{
if (!string.IsNullOrWhiteSpace(kvp.Key))
{
sortDictionary[kvp.Key] = kvp.Value;
}
}
}
if (bodys != null)
{
//按key值升序排序
var dicSort = from objDic in bodys orderby objDic.Key ascending select objDic;
foreach (KeyValuePair<string, string> kvp in dicSort)
{
if (!string.IsNullOrWhiteSpace(kvp.Key))
{
sortDictionary[kvp.Key] = kvp.Value;
}
}
}
StringBuilder sbParam = new StringBuilder();
//按key值升序排序
var dicSortDictionary = from objDic in sortDictionary orderby objDic.Key ascending select objDic;
foreach (KeyValuePair<string, string> kvp in dicSortDictionary)
{
if (!string.IsNullOrWhiteSpace(kvp.Key))
{
if (sbParam.Length > 0)
{
sbParam.Append("&");
}
sbParam.Append(kvp.Key);
if (!string.IsNullOrWhiteSpace(kvp.Value))
{
sbParam.Append("=").Append(kvp.Value);
}
}
}
if (0 < sbParam.Length)
{
sb.Append("?");
sb.Append(sbParam);
}
//artemis/api/resource/v1/org/advance/orgList
return sb.ToString();
}
public static string HmacSHA256(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
public static Dictionary<string, object> ConvertMapTimeStyle(Dictionary<string, object> paramMap)
{
Dictionary<string, object> timeMap = new Dictionary<string, object>();
try
{
foreach (string key in paramMap.Keys)
{
object mapValueObj = paramMap[key];
Dictionary<string, object> dic = mapValueObj as Dictionary<string, object>;
if (dic != null)
{
ConvertMapTimeStyle(dic);
}
//时间格式参数转为ISO8601
DateTime mapDate;
if (DateTime.TryParse(paramMap[key].ToString(), out mapDate))
{
string ISO8601time = mapDate.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz");
timeMap.Add(key, ISO8601time);
}
}
if (timeMap.Count > 0)
{
foreach (string key in timeMap.Keys)
{
paramMap[key] = timeMap[key];
}
}
return paramMap;
}
catch (Exception ex)
{
return paramMap;
}
}
public enum Method
{
GET,
POST_FORM,
POST_STRING,
POST_BYTES,
PUT_FORM,
PUT_STRING,
PUT_BYTES,
DELETE
}
public class Request
{
public Request()
{
}
public Request(Method method, string host, string path, string appKey, string appSecret, int timeout)
{
this.Method = method;
this.Host = host;
this.Path = path;
this.AppKey = appKey;
this.AppSecret = appSecret;
this.Timeout = timeout;
}
public Method Method { get; set; }
public string Host { get; set; }
public string Path { get; set; }
public string AppKey { get; set; }
public string AppSecret { get; set; }
public int Timeout { get; set; }
public Dictionary<string, string> Headers { get; set; }
public Dictionary<string, string> Querys { get; set; }
public Dictionary<string, string> Bodys { get; set; }
public string StringBody { get; set; }
public byte[] BytesBody { get; set; }
public List<string> SignHeaderPrefixList { get; set; }
}
}
}

View File

@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
namespace Infrastructure.Helpers
{
/// <summary>
/// http请求类
/// </summary>
public class HttpHelper
{
private HttpClient _httpClient;
private string _baseIPAddress;
/// <param name="ipaddress">请求的基础IP例如http://192.168.0.33:8080/ </param>
public HttpHelper(string ipaddress = "")
{
this._baseIPAddress = ipaddress;
_httpClient = new HttpClient { BaseAddress = new Uri(_baseIPAddress) };
}
/// <summary>
/// 创建带用户信息的请求客户端
/// </summary>
/// <param name="userName">用户账号</param>
/// <param name="pwd">用户密码当WebApi端不要求密码验证时可传空串</param>
/// <param name="uriString">The URI string.</param>
public HttpHelper(string userName, string pwd = "", string uriString = "")
: this(uriString)
{
if (!string.IsNullOrEmpty(userName))
{
_httpClient.DefaultRequestHeaders.Authorization = CreateBasicCredentials(userName, pwd);
}
}
/// <summary>
/// Get请求数据
/// /// <para>最终以url参数的方式提交</para>
/// <para>yubaolee 2016-3-3 重构与post同样异步调用</para>
/// </summary>
/// <param name="parameters">参数字典,可为空</param>
/// <param name="requestUri">例如/api/Files/UploadFile</param>
/// <returns></returns>
public string Get(Dictionary<string, string> parameters, string requestUri)
{
if (parameters != null)
{
var strParam = string.Join("&", parameters.Select(o => o.Key + "=" + o.Value));
requestUri = string.Concat(ConcatURL(requestUri), '?', strParam);
}
else
{
requestUri = ConcatURL(requestUri);
}
var result = _httpClient.GetStringAsync(requestUri);
return result.Result;
}
/// <summary>
/// Get请求数据
/// <para>最终以url参数的方式提交</para>
/// </summary>
/// <param name="parameters">参数字典</param>
/// <param name="requestUri">例如/api/Files/UploadFile</param>
/// <returns>实体对象</returns>
public T Get<T>(Dictionary<string, string> parameters, string requestUri) where T : class
{
string jsonString = Get(parameters, requestUri);
if (string.IsNullOrEmpty(jsonString))
return null;
return JsonHelper.Instance.Deserialize<T>(jsonString);
}
/// <summary>
/// 以json的方式Post数据 返回string类型
/// <para>最终以json的方式放置在http体中</para>
/// </summary>
/// <param name="entity">实体</param>
/// <param name="requestUri">例如/api/Files/UploadFile</param>
/// <returns></returns>
public string Post(object entity, string requestUri)
{
string request = string.Empty;
if (entity != null)
request = JsonHelper.Instance.Serialize(entity);
HttpContent httpContent = new StringContent(request);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return Post(requestUri, httpContent);
}
/// <summary>
/// 提交字典类型的数据
/// <para>最终以formurlencode的方式放置在http体中</para>
/// <para>李玉宝于2016-07-20 19:01:59</para>
/// </summary>
/// <returns>System.String.</returns>
public string PostDicObj(Dictionary<string, object> para, string requestUri)
{
Dictionary<string, string> temp = new Dictionary<string, string>();
foreach (var item in para)
{
if (item.Value != null)
{
if (item.Value.GetType().Name.ToLower() != "string")
{
temp.Add(item.Key, JsonHelper.Instance.Serialize(item.Value));
}
else
{
temp.Add(item.Key, item.Value.ToString());
}
}
else {
temp.Add(item.Key, "");
}
}
return PostDic(temp, requestUri);
}
/// <summary>
/// Post Dic数据
/// <para>最终以formurlencode的方式放置在http体中</para>
/// <para>李玉宝于2016-07-15 15:28:41</para>
/// </summary>
/// <returns>System.String.</returns>
public string PostDic(Dictionary<string, string> temp, string requestUri)
{
HttpContent httpContent = new FormUrlEncodedContent(temp);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
return Post(requestUri, httpContent);
}
public string PostByte(byte[] bytes, string requestUrl)
{
HttpContent content = new ByteArrayContent(bytes);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return Post(requestUrl, content);
}
private string Post(string requestUrl, HttpContent content)
{
var result = _httpClient.PostAsync(ConcatURL(requestUrl), content);
return result.Result.Content.ReadAsStringAsync().Result;
}
/// <summary>
/// 把请求的URL相对路径组合成绝对路径
/// <para>李玉宝于2016-07-21 9:54:07</para>
/// </summary>
private string ConcatURL(string requestUrl)
{
return new Uri(_httpClient.BaseAddress, requestUrl).OriginalString;
}
private AuthenticationHeaderValue CreateBasicCredentials(string userName, string password)
{
string toEncode = userName + ":" + password;
// The current HTTP specification says characters here are ISO-8859-1.
// However, the draft specification for the next version of HTTP indicates this encoding is infrequently
// used in practice and defines behavior only for ASCII.
Encoding encoding = Encoding.GetEncoding("utf-8");
byte[] toBase64 = encoding.GetBytes(toEncode);
string parameter = Convert.ToBase64String(toBase64);
return new AuthenticationHeaderValue("Basic", parameter);
}
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http.Headers;
namespace Infrastructure.Helpers
{
public class HttpMethods
{
//
// 摘要:
// 创建HttpClient
public static HttpClient CreateHttpClient(string url, IDictionary<string, string> cookies = null)
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
Uri uri = new Uri(url);
if (cookies != null)
{
foreach (string key in cookies.Keys)
{
string cookieHeader = key + "=" + cookies[key];
httpClientHandler.CookieContainer.SetCookies(uri, cookieHeader);
}
}
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, (RemoteCertificateValidationCallback)((object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true));
return new HttpClient(httpClientHandler);
}
return new HttpClient(httpClientHandler);
}
//
// 摘要:
// post 请求
//
// 参数:
// url:
// 请求地址
//
// jsonData:
// 请求参数
public static Task<string> Post(string url, string jsonData)
{
HttpClient httpClient = CreateHttpClient(url);
StringContent stringContent = new StringContent(jsonData);
stringContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
return httpClient.PostAsync(url, stringContent).Result.Content.ReadAsStringAsync();
}
//
// 摘要:
// post 请求
//
// 参数:
// url:
// 请求地址
public static Task<string> Post(string url)
{
HttpClient httpClient = CreateHttpClient(url);
StringContent stringContent = new StringContent("");
stringContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
return httpClient.PostAsync(url, stringContent).Result.Content.ReadAsStringAsync();
}
//
// 摘要:
// post 请求
//
// 参数:
// url:
// 请求地址
//
// req:
// 请求参数
public static Task<string> Post(string url, byte[] req)
{
HttpClient httpClient = CreateHttpClient(url);
ByteArrayContent content = new ByteArrayContent(req);
return httpClient.PostAsync(url, content).Result.Content.ReadAsStringAsync();
}
//
// 摘要:
// get 请求
//
// 参数:
// url:
// 请求地址
public static Task<string> Get(string url)
{
HttpClient httpClient = CreateHttpClient(url);
return httpClient.GetAsync(url).Result.Content.ReadAsStringAsync();
}
}
}

View File

@ -0,0 +1,34 @@
using System.Drawing.Imaging;
using Image = System.Drawing.Image;
namespace Hopetry.App.Common;
public class ImageHelper
{
/// <summary>
/// 图片转换成字节流
/// </summary>
/// <param name="img">要转换的Image对象</param>
/// <returns>转换后返回的字节流</returns>
public static Stream ImgToStream(Image img)
{
byte[] imgByte = ImgToByt(img);
//img.Save(ms, img.RawFormat);//System.Drawing.Imaging.ImageFormat.Jpeg
Stream stream = new MemoryStream(imgByte);
return stream;
}
/// <summary>
/// 图片转换成字节流
/// </summary>
/// <param name="img">要转换的Image对象</param>
/// <returns>转换后返回的字节流</returns>
public static byte[] ImgToByt(Image img)
{
MemoryStream ms = new MemoryStream();
byte[] imagedata = null;
img.Save(ms, ImageFormat.Jpeg);
imagedata = ms.GetBuffer();
return imagedata;
}
}

View File

@ -0,0 +1,50 @@
// <copyright file="ImgHelper.cs" company="openauth.net.cn">
// Copyright (c) 2019 openauth.net.cn. All rights reserved.
// </copyright>
// <author>www.cnblogs.com/yubaolee</author>
// <summary>生成缩略图</summary>
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
namespace Infrastructure.Helpers
{
public class ImgHelper
{
/// <summary>
/// 根据已有图片生成缩略图
/// <para>用法MakeThumbnail(path, tpath, 120, 90, "H");</para>
/// </summary>
/// <param name="originalImagePath">源图片路径</param>
/// <param name="thumbnailPath">缩略图保存路径</param>
/// <param name="width">缩略图的宽度</param>
/// <param name="height">缩略图高度</param>
/// <param name="mode">缩略模式H:指定高度宽度按比例处理W指定宽度高度按比例处理HW按参数指定的高度和宽度</param>
public static void MakeThumbnail(string originalImagePath,
string thumbnailPath,
int width = 120, int height = 90, string mode = "H")
{
using (var originalImage = Image.Load(originalImagePath))
{
int towidth = width; //缩略图宽度
int toheight = height; //缩略图高度
switch (mode)
{
case "HW": //指定高宽缩放(可能变形)
break;
case "W": //指定宽,高按比例
toheight = originalImage.Height * width / originalImage.Width;
break;
case "H": //指定高,宽按比例
towidth = originalImage.Width * height / originalImage.Height;
break;
default:
break;
}
originalImage.Mutate(x => x.Resize(towidth, toheight));
originalImage.Save(thumbnailPath);
}
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace Infrastructure.Helpers
{
public class Md5
{
public static string Encrypt(string str)
{
string pwd = String.Empty;
MD5 md5 = MD5.Create();
// 编码UTF8/Unicode 
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
// 转换成字符串
for (int i = 0; i < s.Length; i++)
{
//格式后的字符是小写的字母
//如果使用大写X则格式后的字符是大写字符
pwd = pwd + s[i].ToString("X");
}
return pwd;
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace Infrastructure.Helpers
{
public class Md5Helper
{
//
// 摘要:
// MD5加密
//
// 参数:
// str:
// 加密字符
//
// code:
// 加密位数16/32
public static string Encrypt(string str, int code)
{
string result = string.Empty;
if (code == 16)
{
result = Hash(str).Substring(8, 16);
}
if (code == 32)
{
result = Hash(str);
}
return result;
}
//
// 摘要:
// 32位MD5加密小写
//
// 参数:
// input:
// 输入字段
public static string Hash(string input)
{
MD5CryptoServiceProvider mD5CryptoServiceProvider = new MD5CryptoServiceProvider();
byte[] array = mD5CryptoServiceProvider.ComputeHash(Encoding.Default.GetBytes(input));
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < array.Length; i++)
{
stringBuilder.Append(array[i].ToString("x2"));
}
return stringBuilder.ToString();
}
}
}

View File

@ -0,0 +1,65 @@
// ***********************************************************************
// Assembly : Infrastructure
// Author : Yubao Li
// Created : 11-23-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 11-23-2015
// ***********************************************************************
// <copyright file="ObjectHelper.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary>
//对象COPY/初始化帮助,通常是防止从视图中传过来的对象属性为空,这其赋初始值
//</summary>
// ***********************************************************************
using System.Reflection;
namespace Infrastructure.Helpers
{
public static class ObjectHelper
{
public static T CopyTo<T>(this object source) where T:class, new()
{
var result = new T();
source.CopyTo(result);
return result;
}
public static void CopyTo<T>(this object source, T target)
where T : class,new()
{
if (source == null)
return;
if (target == null)
{
target = new T();
}
foreach (var property in target.GetType().GetProperties())
{
var propertyValue = source.GetType().GetProperty(property.Name).GetValue(source, null);
if (propertyValue != null)
{
if (propertyValue.GetType().IsClass)
{
}
target.GetType().InvokeMember(property.Name, BindingFlags.SetProperty, null, target, new object[] { propertyValue });
}
}
foreach (var field in target.GetType().GetFields())
{
var fieldValue = source.GetType().GetField(field.Name).GetValue(source);
if (fieldValue != null)
{
target.GetType().InvokeMember(field.Name, BindingFlags.SetField, null, target, new object[] { fieldValue });
}
}
}
}
}

View File

@ -0,0 +1,347 @@
using System.Collections;
using System.Text.RegularExpressions;
using NetModular.DocX.Core;
namespace Infrastructure.Helpers;
public class WordHelper
{
/// <summary>
/// 导出word
/// </summary>
/// <param name="tempFilePath">模板路径</param>
/// <param name="outPath">保存路径</param>
/// <param name="data">数据</param>
public static void Export(string tempFilePath, string outPath, Dictionary<string, object> data)
{
bool isrewrite = true; // true=覆盖已存在的同名文件,false则反之
//if (!System.IO.Directory.Exists(outPath))
//{
// System.IO.Directory.CreateDirectory(outPath);
//}
File.Copy(tempFilePath, outPath, isrewrite);
//新建一个Word文档加载Load的方法和Create使用一样。
using (DocX document = DocX.Load(outPath))
{
ReplaceDoc(document, data); //普通文本替换
ReplaceTable(document, data); //表格处理
ReplaceList(document, data); //文本列表处理
document.Save(); //保存
}
}
private static void ReplaceDoc(DocX doc, Dictionary<string, object> data)
{
foreach (var item in doc.Paragraphs)
{
ReplaceParagraph(item, data);
}
}
private static void ReplaceList(DocX doc, Dictionary<string, object> data)
{
//一定要在 普通文本替换和表格处理之后
foreach (var p in doc.Paragraphs)
{
var li = GetListInfo(p, data);
if (li.IsList)
{
var pc = li.PTemp;
for (int i = 0; i < li.Data.Count; i++)
{
var pt = pc.InsertParagraphAfterSelf(p);
if (li.IsDict)
{
pc = ReplaceParagraph(pt, (Dictionary<string, object>)li.Data[i]);
}
else
{
pc = ReplaceParagraph(pt, li.Data[i]);
}
}
//删除模板行
li.PTemp.Remove(false);
}
else
{
//do nonthing
}
}
}
private static void ReplaceTable(DocX doc, Dictionary<string, object> data)
{
var tbs = doc.Tables;
foreach (var table in tbs)
{
//需要先判断表格是列表还是表单
var ti = GetTableInfo(table, data);
if (ti.IsList)
{
for (int i = 0; i < ti.Data.Count; i++)
{
var rt = table.InsertRow(ti.RowTemp);
rt.Height = ti.RowTemp.Height;
rt.MinHeight = ti.RowTemp.MinHeight;
if (ti.IsDict)
{
ReplaceRow(rt, (Dictionary<string, object>)ti.Data[i]);
}
else
{
ReplaceRow(rt, ti.Data[i]);
}
}
//删除模板行
ti.RowTemp.Remove();
}
else
{
//do nonthing
}
}
}
private static void ReplaceRow(Row row, Dictionary<string, object> data)
{
foreach (var cell in row.Cells)
{
foreach (var item in cell.Paragraphs)
{
ReplaceParagraph(item, data);
}
}
}
private static void ReplaceRow(Row row, object data)
{
foreach (var cell in row.Cells)
{
foreach (var item in cell.Paragraphs)
{
ReplaceParagraph(item, data);
}
}
}
private static Paragraph ReplaceParagraph(Paragraph p, Dictionary<string, object> data)
{
Paragraph pr = p;
var ms = GetMatches(p.Text);
var ks = new List<string>();
var rs = new List<string>();
foreach (Match m in ms)
{
if (m.Groups.Count > 1)
{
string text = m.Groups[1].Value;
if (text.Contains("."))
{
var ts = text.Split(".");
text = ts[ts.Length - 1];
}
ks.Add(text);
rs.Add(m.Value);
}
}
bool isCt = data.Any(op => ks.Any(o => o.Contains(op.Key)));
bool isReplace = false;
if (isCt)
{
if (ks.Count > 1)
{
for (int i = 0; i < ks.Count; i++)
{
if (data.ContainsKey(ks[i]))
{
p.ReplaceText(rs[i], data[ks[i]]?.ToString());
}
}
}
else if (ks.Count == 1)
{
string text = ks[0];
if (data.ContainsKey(text))
{
var ct = data[text]?.ToString();
var cts = ResolveText(ct);
var pc = p;
foreach (var item2 in cts)
{
if (string.IsNullOrWhiteSpace(item2)) continue;
var pt = pc.InsertParagraphAfterSelf(p);
pt.ReplaceText(rs[0], item2);
pc = pt;
pr = pc;
}
isReplace = true;
}
}
if (isReplace)
{
//删除原来段落
p.Remove(false);
}
}
return pr;
}
private static Paragraph ReplaceParagraph(Paragraph p, object data)
{
var ms = GetMatches(p.Text);
var isReplace = false;
Paragraph pr = p;
foreach (Match item1 in ms)
{
if (item1.Groups.Count > 1)
{
string text = item1.Groups[1].Value;
var ct = data?.ToString();
var cts = ResolveText(ct);
var pc = p;
foreach (var item2 in cts)
{
var pt = pc.InsertParagraphAfterSelf(p);
pt.ReplaceText(item1.Value, item2);
pc = pt;
pr = pc;
}
isReplace = true;
}
}
if (isReplace)
{
//删除原来段落
p.Remove(false);
}
return pr;
}
private static IList<string> ResolveText(string text)
{
if (string.IsNullOrEmpty(text)) return new List<string>();
text = text.Replace("\r\n", "\n").Replace("\r", "\n");
return text.Split('\n');
}
private static MatchCollection GetMatches(string text)
{
if (string.IsNullOrEmpty(text)) text = "";
Regex regex = new Regex("[#|\\$]([a-zA-Z0-9_.]+?)[#|\\$]",
RegexOptions.IgnoreCase | RegexOptions.Multiline);
return regex.Matches(text);
}
/// <summary>
/// 只获取列表匹配项
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private static MatchCollection GetListMatches(string text)
{
if (string.IsNullOrEmpty(text)) text = "";
Regex regex = new Regex("\\$([a-zA-Z0-9_.]+?)\\$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
return regex.Matches(text);
}
//纯辅助方法
private class TableInfo
{
public bool IsList { get; set; }
public bool IsDict { get; set; }
public Row RowTemp { get; set; }
public IList<object> Data { get; set; }
}
//判断表格是列表还是表单
private static TableInfo GetTableInfo(Table table, Dictionary<string, object> data)
{
TableInfo result = new TableInfo();
var r0 = table.Rows[table.Rows.Count - 1];
var c0 = r0.Cells[r0.Cells.Count - 1];
var ct = c0.Paragraphs[0].Text;
var ms = GetListMatches(ct);
foreach (Match item in ms)
{
if (item.Groups.Count > 1)
{
string text = item.Groups[1].Value;
if (text.Contains("."))
{
result.IsDict = true;
text = text.Split('.')[0];
}
if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表
{
result.RowTemp = r0;
result.IsList = true;
result.Data = new List<object>();
foreach (var item1 in (data[text] as IList))
{
result.Data.Add(item1);
}
break;
}
}
}
return result;
}
private class ListInfo
{
public bool IsList { get; set; }
public bool IsDict { get; set; }
public Paragraph PTemp { get; set; }
public IList<object> Data { get; set; }
}
private static ListInfo GetListInfo(Paragraph p, Dictionary<string, object> data)
{
ListInfo result = new ListInfo();
var ms = GetListMatches(p.Text);
foreach (Match item in ms)
{
if (item.Groups.Count > 1)
{
string text = item.Groups[1].Value;
if (text.Contains("."))
{
result.IsDict = true;
text = text.Split('.')[0];
}
if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表
{
result.PTemp = p;
result.IsList = true;
result.Data = new List<object>();
foreach (var item1 in (data[text] as IList))
{
result.Data.Add(item1);
}
break;
}
}
}
return result;
}
}

View File

@ -0,0 +1,710 @@
using System.Xml;
namespace Infrastructure.Helpers
{
/// <summary>
/// XMLHelper参数
/// </summary>
public class XmlParameter
{
private string _name;
private string _innerText;
private string _namespaceOfPrefix;
private AttributeParameter[] _attributes;
public XmlParameter() { }
public XmlParameter(string name, params AttributeParameter[] attParas) : this(name, null, null, attParas) { }
public XmlParameter(string name, string innerText, params AttributeParameter[] attParas) : this(name, innerText, null, attParas) { }
public XmlParameter(string name, string innerText, string namespaceOfPrefix, params AttributeParameter[] attParas)
{
this._name = name;
this._innerText = innerText;
this._namespaceOfPrefix = namespaceOfPrefix;
this._attributes = attParas;
}
/// <summary>
/// 节点名称
/// </summary>
public string Name
{
get { return this._name; }
set { this._name = value; }
}
/// <summary>
/// 节点文本
/// </summary>
public string InnerText
{
get { return this._innerText; }
set { this._innerText = value; }
}
/// <summary>
/// 节点前缀xmlns声明(命名空间URI)
/// </summary>
public string NamespaceOfPrefix
{
get { return this._namespaceOfPrefix; }
set { this._namespaceOfPrefix = value; }
}
/// <summary>
/// 节点属性集
/// </summary>
public AttributeParameter[] Attributes
{
get { return this._attributes; }
set { this._attributes = value; }
}
}
/// <summary>
/// 节点属性参数
/// </summary>
public class AttributeParameter
{
private string _name;
private string _value;
public AttributeParameter() { }
public AttributeParameter(string attributeName, string attributeValue)
{
this._name = attributeName;
this._value = attributeValue;
}
/// <summary>
/// 属性名称
/// </summary>
public string Name
{
get { return this._name; }
set { this._name = value; }
}
/// <summary>
/// 属性值
/// </summary>
public string Value
{
get { return this._value; }
set { this._value = value; }
}
}
public class XMLHelper
{
private static string _xPath;
/// <summary>
/// xml文件路径
/// </summary>
public static string XmlPath
{
get { return _xPath; }
set { _xPath = value; }
}
private static string _configName = "XmlPath";
/// <summary>
/// 配置文件节点名称请设置在AppSettings节点下
/// </summary>
public static string ConfigName
{
get { return _configName; }
set { _configName = value; GetConfig(); }
}
/// <summary>
/// 从配置文件读取xml路径
/// </summary>
static void GetConfig()
{
//if (string.IsNullOrEmpty(_xPath))
//{
// try
// {
// _xPath = ConfigurationManager.AppSettings[_configName];
// }
// catch { }
//}
}
static XMLHelper() { GetConfig(); }
#region private AppendChild
/// <summary>
/// 添加一个子节点
/// </summary>
/// <param name="xDoc">XmlDocument对象</param>
/// <param name="parentNode">父节点</param>
/// <param name="xlParameter">Xml参数</param>
private static void AppendChild(XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] xlParameter)
{
foreach (XmlParameter xpar in xlParameter)
{
XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xpar.Name, null);
string ns = string.IsNullOrEmpty(xpar.NamespaceOfPrefix) ? "" : newNode.GetNamespaceOfPrefix(xpar.NamespaceOfPrefix);
foreach (AttributeParameter attp in xpar.Attributes)
{
XmlNode attr = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns);
attr.Value = attp.Value;
newNode.Attributes.SetNamedItem(attr);
}
newNode.InnerText = xpar.InnerText;
parentNode.AppendChild(newNode);
}
}
#endregion
#region private AddEveryNode
private static void AddEveryNode(XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] paras)
{
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst)
{
if (xns.Name == parentNode.Name)
{
AppendChild(xDoc, xns, paras);
}
else
{
foreach (XmlNode xn in xns)
{
if (xn.Name == parentNode.Name)
{
AppendChild(xDoc, xn, paras);
}
}
}
}
}
#endregion
#region private GetXmlDom
/// <summary>
/// 获得一个XmlDocument对象
/// </summary>
/// <returns></returns>
private static XmlDocument GetXmlDom()
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(_xPath);
return xdoc;
}
#endregion
#region CreateXmlFile
/// <summary>
/// 创建一个XML文档成功创建后操作路径将直接指向该文件
/// </summary>
/// <param name="fileName">文件物理路径名</param>
/// <param name="rootNode">根结点名称</param>
/// <param name="elementName">元素节点名称</param>
/// <param name="xmlParameter">XML参数</param>
public static void CreateXmlFile(string fileName, string rootNode, string elementName, params XmlParameter[] xmlParameter)
{
XmlDocument xDoc = new XmlDocument();
XmlNode xn = xDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
xDoc.AppendChild(xn);
XmlNode root = xDoc.CreateElement(rootNode);
xDoc.AppendChild(root);
XmlNode ln = xDoc.CreateNode(XmlNodeType.Element, elementName, null);
AppendChild(xDoc, ln, xmlParameter);
root.AppendChild(ln);
try
{
xDoc.Save(fileName);
_xPath = fileName;
}
catch
{
throw;
}
}
/// <summary>
/// 创建一个XML文档成功创建后操作路径将直接指向该文件
/// </summary>
/// <param name="fileName">文件物理路径名</param>
/// <param name="xmlString">xml字符串</param>
public static void CreateXmlFile(string fileName, string xmlString)
{
XmlDocument xDoc = new XmlDocument();
try
{
xDoc.LoadXml(xmlString);
xDoc.Save(fileName);
_xPath = fileName;
}
catch { throw; }
}
#endregion
#region AddNewNode
/// <summary>
/// 添加新节点
/// </summary>
/// <param name="parentNode">新节点的父节点对象</param>
/// <param name="xmlParameter">Xml参数对象</param>
public static void AddNewNode(XmlNode parentNode, params XmlParameter[] xmlParameter)
{
XmlDocument xDoc = GetXmlDom();
if (parentNode.Name == xDoc.DocumentElement.Name)
{
XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xDoc.DocumentElement.ChildNodes[0].Name, null);
AppendChild(xDoc, newNode, xmlParameter);
xDoc.DocumentElement.AppendChild(newNode);
}
else
{
AddEveryNode(xDoc, parentNode, xmlParameter);
}
xDoc.Save(_xPath);
}
/// <summary>
/// 添加新节点
/// </summary>
/// <param name="xDoc">XmlDocument对象</param>
/// <param name="parentName">新节点的父节点名称</param>
/// <param name="xmlParameter">XML参数对象</param>
public static void AddNewNode(string parentName, params XmlParameter[] xmlParameter)
{
XmlDocument xDoc = GetXmlDom();
XmlNode parentNode = GetNode(xDoc, parentName);
if (parentNode == null) return;
if (parentNode.Name == xDoc.DocumentElement.Name)
{
XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xDoc.DocumentElement.ChildNodes[0].Name, null);
AppendChild(xDoc, newNode, xmlParameter);
xDoc.DocumentElement.AppendChild(newNode);
}
else
{
AddEveryNode(xDoc, parentNode, xmlParameter);
}
xDoc.Save(_xPath);
}
#endregion
#region AddAttribute
/// <summary>
/// 添加节点属性
/// </summary>
/// <param name="node">节点对象</param>
/// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
/// <param name="attributeName">新属性名称</param>
/// <param name="attributeValue">属性值</param>
public static void AddAttribute(XmlNode node, string namespaceOfPrefix, string attributeName, string attributeValue)
{
XmlDocument xDoc = GetXmlDom();
string ns = string.IsNullOrEmpty(namespaceOfPrefix) ? "" : node.GetNamespaceOfPrefix(namespaceOfPrefix);
XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attributeName, ns == "" ? null : ns);
xn.Value = attributeValue;
node.Attributes.SetNamedItem(xn);
xDoc.Save(_xPath);
}
/// <summary>
/// 添加节点属性
/// </summary>
/// <param name="node">节点对象</param>
/// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
/// <param name="attributeParameters">节点属性参数</param>
public static void AddAttribute(XmlNode node, string namespaceOfPrefix, params AttributeParameter[] attributeParameters)
{
XmlDocument xDoc = GetXmlDom();
string ns = string.IsNullOrEmpty(namespaceOfPrefix) ? "" : node.GetNamespaceOfPrefix(namespaceOfPrefix);
foreach (AttributeParameter attp in attributeParameters)
{
XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns);
xn.Value = attp.Value;
node.Attributes.SetNamedItem(xn);
}
xDoc.Save(_xPath);
}
/// <summary>
/// 添加节点属性
/// </summary>
/// <param name="nodeName">节点名称</param>
/// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
/// <param name="attributeName">新属性名称</param>
/// <param name="attributeValue">属性值</param>
public static void AddAttribute(string nodeName, string namespaceOfPrefix, string attributeName, string attributeValue)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
for (int i = 0; i < xlst.Count; i++)
{
XmlNode node = GetNode(xlst[i], nodeName);
if (node == null) break;
AddAttribute(node, namespaceOfPrefix, attributeName, attributeValue);
}
xDoc.Save(_xPath);
}
/// <summary>
/// 添加节点属性
/// </summary>
/// <param name="nodeName">节点名称</param>
/// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
/// <param name="attributeParameters">节点属性参数</param>
public static void AddAttribute(string nodeName, string namespaceOfPrefix, params AttributeParameter[] attributeParameters)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
for (int i = 0; i < xlst.Count; i++)
{
XmlNode node = GetNode(xlst[i], nodeName);
if (node == null) break;
AddAttribute(node, namespaceOfPrefix, attributeParameters);
}
xDoc.Save(_xPath);
}
#endregion
#region GetNode
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="nodeName">节点名称</param>
/// <returns></returns>
public static XmlNode GetNode(string nodeName)
{
XmlDocument xDoc = GetXmlDom();
if (xDoc.DocumentElement.Name == nodeName) return (XmlNode)xDoc.DocumentElement;
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst) // 遍历所有子节点
{
if (xns.Name == nodeName) return xns;
else
{
XmlNode xn = GetNode(xns, nodeName);
if (xn != null) return xn;
}
}
return null;
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="node">节点对象</param>
/// <param name="nodeName">节点名称</param>
/// <returns></returns>
public static XmlNode GetNode(XmlNode node, string nodeName)
{
foreach (XmlNode xn in node)
{
if (xn.Name == nodeName) return xn;
else
{
XmlNode tmp = GetNode(xn, nodeName);
if (tmp != null) return tmp;
}
}
return null;
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="index">节点索引</param>
/// <param name="nodeName">节点名称</param>
public static XmlNode GetNode(int index, string nodeName)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
if (nlst.Count <= index) return null;
if (nlst[index].Name == nodeName) return (XmlNode)nlst[index];
foreach (XmlNode xn in nlst[index])
{
return GetNode(xn, nodeName);
}
return null;
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="node">节点对象</param>
/// <param name="nodeName">节点名称</param>
/// <param name="innerText">节点内容</param>
public static XmlNode GetNode(XmlNode node, string nodeName, string innerText)
{
foreach (XmlNode xn in node)
{
if (xn.Name == nodeName && xn.InnerText == innerText) return xn;
else
{
XmlNode tmp = GetNode(xn, nodeName, innerText);
if (tmp != null) return tmp;
}
}
return null;
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="nodeName">节点名称</param>
/// <param name="innerText">节点内容</param>
public static XmlNode GetNode(string nodeName, string innerText)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst) // 遍历所有子节点
{
if (xns.Name == nodeName && xns.InnerText == innerText) return xns;
XmlNode tmp = GetNode(xns, nodeName, innerText);
if (tmp != null) return tmp;
}
return null;
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="xmlParameter">XML参数</param>
public static XmlNode GetNode(XmlParameter xmlParameter)
{
return GetNode(xmlParameter.Name, xmlParameter.InnerText);
}
/// <summary>
/// 获取指定节点名称的节点对象
/// </summary>
/// <param name="node">节点对象</param>
/// <param name="xmlParameter">XML参数</param>
public static XmlNode GetNode(XmlNode node, XmlParameter xmlParameter)
{
return GetNode(node, xmlParameter.Name, node.InnerText);
}
#endregion
#region UpdateNode
private static void UpdateNode(XmlNode node, XmlParameter xmlParameter)
{
node.InnerText = xmlParameter.InnerText;
for (int i = 0; i < xmlParameter.Attributes.Length; i++)
{
for (int j = 0; j < node.Attributes.Count; j++)
{
if (node.Attributes[j].Name == xmlParameter.Attributes[i].Name)
{
node.Attributes[j].Value = xmlParameter.Attributes[i].Value;
}
}
}
}
private static void UpdateNode(XmlNode node, string innerText, AttributeParameter[] attributeParameters)
{
node.InnerText = innerText;
for (int i = 0; i < attributeParameters.Length; i++)
{
for (int j = 0; j < node.Attributes.Count; j++)
{
if (node.Attributes[j].Name == attributeParameters[i].Name)
{
node.Attributes[j].Value = attributeParameters[i].Value;
}
}
}
}
/// <summary>
/// 修改节点的内容
/// </summary>
/// <param name="index">节点索引</param>
/// <param name="xmlParameter">XML参数对象</param>
public static void UpdateNode(int index, XmlParameter xmlParameter)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
if (nlst.Count <= index) return;
if (nlst[index].Name == xmlParameter.Name)
{
UpdateNode(nlst[index], xmlParameter);
}
else
{
foreach (XmlNode xn in nlst[index])
{
XmlNode xnd = GetNode(xn, xmlParameter.Name);
if (xnd != null)
{
UpdateNode(xnd, xmlParameter);
}
}
}
xDoc.Save(_xPath);
}
/// <summary>
/// 修改节点的内容
/// </summary>
/// <param name="index">节点索引</param>
/// <param name="nodeName">节点名称</param>
/// <param name="newInnerText">修改后的内容</param>
public static void UpdateNode(int index, string nodeName, string newInnerText)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
if (nlst.Count <= index) return;
if (nlst[index].Name == nodeName)
{
nlst[index].InnerText = newInnerText;
}
else
{
foreach (XmlNode xn in nlst[index])
{
XmlNode xnd = GetNode(xn, nodeName);
if (xnd != null)
{
xnd.InnerText = newInnerText;
}
}
}
xDoc.Save(_xPath);
}
/// <summary>
/// 修改节点的内容
/// </summary>
/// <param name="xmlParameter">XmlParameter对象</param>
/// <param name="innerText">修改后的内容</param>
/// <param name="attributeParameters">需要修改的属性</param>
public static void UpdateNode(XmlParameter xmlParameter, string innerText, params AttributeParameter[] attributeParameters)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst) // 遍历所有子节点
{
if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText)
{
UpdateNode(xns, innerText, attributeParameters);
break;
}
XmlNode tmp = GetNode(xns, xmlParameter);
if (tmp != null)
{
UpdateNode(tmp, innerText, attributeParameters);
break;
}
}
xDoc.Save(_xPath);
}
#endregion
#region DeleteNode
/// <summary>
/// 删除节点
/// </summary>
/// <param name="index">节点索引</param>
public static void DeleteNode(int index)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
nlst[index].ParentNode.RemoveChild(nlst[index]);
xDoc.Save(_xPath);
}
/// <summary>
/// 删除节点
/// </summary>
/// <param name="nodeList">需要删除的节点对象</param>
public static void DeleteNode(params XmlNode[] nodeList)
{
XmlDocument xDoc = GetXmlDom();
foreach (XmlNode xnl in nodeList)
{
foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes)
{
if (xnl.Equals(xn))
{
xn.ParentNode.RemoveChild(xn);
break;
}
}
}
xDoc.Save(_xPath);
}
/// <summary>
/// 删除节点
/// </summary>
/// <param name="xDoc">XmlDocument对象</param>
/// <param name="nodeName">节点名称</param>
/// <param name="nodeText">节点内容</param>
public static void DeleteNode(string nodeName, string nodeText)
{
XmlDocument xDoc = GetXmlDom();
foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes)
{
if (xn.Name == nodeName)
{
if (xn.InnerText == nodeText)
{
xn.ParentNode.RemoveChild(xn);
return;
}
}
else
{
XmlNode node = GetNode(xn, nodeName);
if (node != null && node.InnerText == nodeText)
{
node.ParentNode.ParentNode.RemoveChild(node.ParentNode);
return;
}
}
}
xDoc.Save(_xPath);
}
#endregion
#region SetAttribute
/// <summary>
/// 修改属性值
/// </summary>
/// <param name="elem">元素对象</param>
/// <param name="attps">属性参数</param>
private static void SetAttribute(XmlElement elem, params AttributeParameter[] attps)
{
foreach (AttributeParameter attp in attps)
{
elem.SetAttribute(attp.Name, attp.Value);
}
}
/// <summary>
/// 修改属性值
/// </summary>
/// <param name="xmlParameter">XML参数</param>
/// <param name="attributeParameters">属性参数</param>
public static void SetAttribute(XmlParameter xmlParameter, params AttributeParameter[] attributeParameters)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst) // 遍历所有子节点
{
if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText)
{
SetAttribute((XmlElement)xns, attributeParameters);
break;
}
XmlNode tmp = GetNode(xns, xmlParameter);
if (tmp != null)
{
SetAttribute((XmlElement)tmp, attributeParameters);
break;
}
}
xDoc.Save(_xPath);
}
/// <summary>
/// 修改属性值
/// </summary>
/// <param name="xmlParameter">XML参数</param>
/// <param name="attributeValue">新属性值</param>
public static void SetAttribute(XmlParameter xmlParameter, string attributeName, string attributeValue)
{
XmlDocument xDoc = GetXmlDom();
XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
foreach (XmlNode xns in nlst) // 遍历所有子节点
{
if (xns.Name == xmlParameter.Name && xns.InnerText == xmlParameter.InnerText)
{
((XmlElement)xns).SetAttribute(attributeName, attributeValue);
break;
}
XmlNode tmp = GetNode(xns, xmlParameter);
if (tmp != null)
{
((XmlElement)tmp).SetAttribute(attributeName, attributeValue);
break;
}
}
xDoc.Save(_xPath);
}
#endregion
}
}

View File

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\net5.0\Infrastructure.xml</DocumentationFile>
<NoWarn>1701;1702;1591;1573;1572;1570</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="DocXCore.Standard" Version="1.0.1" />
<PackageReference Include="EnyimMemcachedCore" Version="2.6.4" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="NetTopologySuite.IO.Esri.Shapefile" Version="1.0.0" />
<PackageReference Include="NetTopologySuite.IO.ShapeFile" Version="2.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NPOI" Version="2.5.6" />
<PackageReference Include="NUnit" Version="3.13.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="PinYinConverterCore" Version="1.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
<PackageReference Include="StackExchange.Redis" Version="2.6.111" />
</ItemGroup>
<ItemGroup>
<None Update="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

83
Infrastructure/Json.cs Normal file
View File

@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace Infrastructure
{
/// <summary>
/// Json操作
/// </summary>
public static class Json
{
public static object ToJson(this string Json)
{
return Json == null ? null : JsonConvert.DeserializeObject(Json);
}
public static string ToJson(this object obj)
{
var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
return JsonConvert.SerializeObject(obj, timeConverter);
}
public static string ToJson(this object obj, string datetimeformats)
{
var timeConverter = new IsoDateTimeConverter { DateTimeFormat = datetimeformats };
return JsonConvert.SerializeObject(obj, timeConverter);
}
public static T ToObject<T>(this string Json)
{
return Json == null ? default(T) : JsonConvert.DeserializeObject<T>(Json);
}
public static List<T> ToList<T>(this string Json)
{
return Json == null ? null : JsonConvert.DeserializeObject<List<T>>(Json);
}
public static DataTable ToTable(this string Json)
{
return Json == null ? null : JsonConvert.DeserializeObject<DataTable>(Json);
}
public static JObject ToJObject(this string Json)
{
return Json == null ? JObject.Parse("{}") : JObject.Parse(Json.Replace("&nbsp;", ""));
}
/// <summary>
/// 转换成JToken
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static JToken ToJToken(this string str)
{
try
{
var jToken = (JToken)JsonConvert.DeserializeObject(str);
return jToken;
}
catch (Exception ex)
{
return null;
}
}
/// <summary>
/// 检查请求参数是否异常
/// </summary>
/// <param name="obj"></param>
public static void CheckReqIsNull(this object obj)
{
if (obj == null) throw new Exception("数据异常,请检查输入信息是否正确。");
}
/// <summary>
/// 初始化数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static List<T> InitListData<T>(this List<T> list)
{
if (list == null) list = new List<T>();
return list;
}
}
}

View File

@ -0,0 +1,61 @@
// ***********************************************************************
// Assembly : Infrastructure
// Author : Yubao Li
// Created : 09-07-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 09-07-2015
// ***********************************************************************
// <copyright file="GuidConverter.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary>解决JSON转换空GUID问题</summary>
// ***********************************************************************
using System;
using Newtonsoft.Json;
namespace Infrastructure
{
public class GuidConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(Guid));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Guid result = Guid.Empty;
if (reader.Value == null) return result;
Guid.TryParse(reader.Value.ToString(), out result);
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
public class DecimalConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(decimal));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
decimal result = 0;
if (reader.Value == null) return result;
decimal.TryParse(reader.Value.ToString(), out result);
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
}

View File

@ -0,0 +1,55 @@
// ***********************************************************************
// Assembly : FairUtility
// Author : Yubao Li
// Created : 08-12-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 08-12-2015
// ***********************************************************************
// <copyright file="JsonHelper.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary>json序列化帮助类</summary>
// ***********************************************************************
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Infrastructure
{
public class JsonHelper
{
private static JsonHelper _jsonHelper = new JsonHelper();
public static JsonHelper Instance { get { return _jsonHelper; } }
public string Serialize(object obj)
{
return JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
}
public string SerializeByConverter(object obj, params JsonConverter[] converters)
{
return JsonConvert.SerializeObject(obj, converters);
}
public T Deserialize<T>(string input)
{
return JsonConvert.DeserializeObject<T>(input);
}
public T DeserializeByConverter<T>(string input,params JsonConverter[] converter)
{
return JsonConvert.DeserializeObject<T>(input, converter);
}
public T DeserializeBySetting<T>(string input, JsonSerializerSettings settings)
{
return JsonConvert.DeserializeObject<T>(input, settings);
}
private object NullToEmpty(object obj)
{
return null;
}
}
}

View File

@ -0,0 +1,24 @@
namespace Infrastructure
{
public class KeyDescription
{
/// <summary>
/// 键值
/// </summary>
public string Key { get; set; }
/// <summary>
/// 键的描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 前端是否显示
/// </summary>
public bool Browsable { get; set; }
/// <summary>
/// 字段类型
/// </summary>
public string Type { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Builder;
namespace Infrastructure.Middleware
{
/// <summary>
///
/// </summary>
public static class ApplicationBuilderExtension
{
/// <summary>
/// 注入日志中间件
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseLogMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestResponseLoggingMiddleware>();
}
}
}

View File

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Infrastructure.Middleware
{
/// <summary>
/// 请求与返回中间件
/// </summary>
public class RequestResponseLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestResponseLoggingMiddleware> _log;
/// <summary>
///
/// </summary>
public RequestResponseLoggingMiddleware(RequestDelegate next, ILogger<RequestResponseLoggingMiddleware> log)
{
_next = next;
_log = log;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
#region 这里可以加入正则验证context.Path。 过滤不需要记录日志的api
//var path = context.Request.Path.ToString().ToLower();
//if (path.Contains("/index") || path.Contains("/check") ||
// path.Contains("/swagger") || path.Contains("/getsysdatas") || path.Contains("/load"))
//{
await CatchNext(context);
// return;
//}
#endregion
#region 日志
// 启用耗时 日志记录
//var stopwatch = new Stopwatch();
//stopwatch.Start();
//var logData = new Dictionary<string, object>();
//var request = context.Request;
//logData.Add("request.url", request.Path.ToString());
//logData.Add("request.headers",
// request.Headers.ToDictionary(x => x.Key, v => string.Join(";", v.Value.ToList())));
//logData.Add("request.method", request.Method);
//logData.Add("request.executeStartTime", DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
////追踪实别器
//logData.Add("traceIdentifier", context.TraceIdentifier);
//// 获取请求body内容
//if (request.Method.ToLower().Equals("post"))
//{
// // 启用倒带功能,就可以让 Request.Body 可以再次读取
// request.EnableBuffering();
// // 文件上传 记录文件信息
// if (path.Contains("/upload"))
// {
// var content = string.Join(",", request.Form.Files.Select(item => item.FileName));
// logData.Add("request.body", $"收到上传文件:{content}");
// }
// else
// {
// var sr = new StreamReader(request.Body, Encoding.UTF8);
// var content = sr.ReadToEndAsync().Result;
// logData.Add("request.body", content);
// request.Body.Position = 0;
// }
//}
//else if (request.Method.ToLower().Equals("get"))
//{
// logData.Add("request.body", request.QueryString.Value);
//}
//// 获取Response.Body内容
//var originalBodyStream = context.Response.Body;
//using (var responseBody = new MemoryStream())
//{
// context.Response.Body = responseBody;
// await CatchNext(context);
// if (!logData.ContainsKey("response.body"))
// {
// logData.Add("response.body", await GetResponse(context.Response));
// }
// logData.Add("response.executeEndTime", DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
// logData.Add("response.statusCode", context.Response.StatusCode);
// await responseBody.CopyToAsync(originalBodyStream);
//}
//// 响应完成记录时间和存入日志
//context.Response.OnCompleted(() =>
//{
// try
// {
// stopwatch.Stop();
// logData.Add("elapsedTime", stopwatch.ElapsedMilliseconds + "ms");
// var json = JsonHelper.Instance.Serialize(logData);
// _log.LogInformation(json);
// return Task.CompletedTask;
// }
// catch (Exception ex)
// {
// return Task.FromException(ex);
// }
//});
#endregion
}
private async Task CatchNext(HttpContext context)
{
var logData = new Dictionary<string, object>();
try
{
var request = context.Request;
request.EnableBuffering();
// 获取请求body内容
if (request.Method.ToLower().Equals("post"))
{
// 启用倒带功能,就可以让 Request.Body 可以再次读取
request.EnableBuffering();
// 文件上传 记录文件信息
var sr = new StreamReader(request.Body, Encoding.UTF8);
var content = sr.ReadToEndAsync().Result;
logData.Add("request.body", content);
request.Body.Position = 0;
}
else if (request.Method.ToLower().Equals("get"))
{
logData.Add("request.body", request.QueryString.Value);
}
await _next(context);
}
catch (Exception ex)
{
_log.LogError(JsonHelper.Instance.Serialize(logData));
_log.LogError(ex, "系统错误日志,管道捕获");
context.Response.StatusCode = 200;
context.Response.ContentType = "application/json; charset=utf-8";
var result = new { code = 500, message = ex.Message ?? "系统错误,请稍后再试" };
await context.Response.WriteAsync(JsonHelper.Instance.Serialize(result));
}
}
/// <summary>
/// 获取响应内容
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
private static async Task<string> GetResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);
return text;
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Linq;
using System.Linq.Expressions;
namespace Infrastructure
{
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
}

View File

@ -0,0 +1,52 @@
using System.IO;
using Infrastructure.Extensions;
using Infrastructure.Extensions.AutofacManager;
using Microsoft.Extensions.Hosting;
namespace Infrastructure.Provider
{
public interface IPathProvider : IDependency
{
string MapPath(string path);
string MapPath(string path, bool rootPath);
IHostEnvironment GetHostingEnvironment();
}
public class PathProvider : IPathProvider
{
private IHostEnvironment _hostingEnvironment;
public PathProvider(IHostEnvironment environment)
{
_hostingEnvironment = environment;
}
public IHostEnvironment GetHostingEnvironment()
{
return _hostingEnvironment;
}
/// <summary>
/// 获取服务器文件路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public string MapPath(string path)
{
return MapPath(path, false);
}
/// <summary>
/// 获取wwwroot路径
/// </summary>
/// <param name="path"></param>
/// <param name="rootPath">是否获取wwwroot路径</param>
/// <returns></returns>
public string MapPath(string path, bool rootPath)
{
if (rootPath)
{
return Path.Combine(_hostingEnvironment.ContentRootPath,"wwwroot").ReplacePath();
}
return Path.Combine(_hostingEnvironment.ContentRootPath, path).ReplacePath();
}
}
}

View File

@ -0,0 +1,45 @@
namespace Infrastructure
{
public class Response
{
/// <summary>
/// 操作消息【当Status不为 200时显示详细的错误信息】
/// </summary>
public string Message { get; set; }
/// <summary>
/// 操作状态码200为正常
/// </summary>
public int Code { get; set; }
public Response()
{
Code = 200;
Message = "操作成功";
}
}
public class ResponsePage<T> : Response
{
public int Count { get; set; }
}
public class PageInfo<T>
{
public T Items { get; set; }
public int Total { get; set; }
}
/// <summary>
/// WEBAPI通用返回泛型基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class Response<T> : Response
{
/// <summary>
/// 回传的结果
/// </summary>
public T Result { get; set; }
}
}

View File

@ -0,0 +1,29 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
namespace Yitter.IdGenerator
{
public interface IIdGenerator
{
/// <summary>
/// 生成过程中产生的事件
/// </summary>
//Action<OverCostActionArg> GenIdActionAsync { get; set; }
/// <summary>
/// 生成新的long型Id
/// </summary>
/// <returns></returns>
long NewLong();
// Guid NewGuid();
}
}

View File

@ -0,0 +1,22 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Yitter.IdGenerator
{
internal interface ISnowWorker
{
//Action<OverCostActionArg> GenAction { get; set; }
long NextId();
}
}

View File

@ -0,0 +1,92 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Yitter.IdGenerator
{
public class IdGeneratorOptions
{
/// <summary>
/// 雪花计算方法
/// 1-漂移算法|2-传统算法默认1
/// </summary>
public virtual short Method { get; set; } = 1;
/// <summary>
/// 基础时间UTC格式
/// 不能超过当前系统时间
/// </summary>
public virtual DateTime BaseTime { get; set; } = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc);
/// <summary>
/// 机器码
/// 必须由外部设定,最大值 2^WorkerIdBitLength-1
/// </summary>
public virtual ushort WorkerId { get; set; } = 0;
/// <summary>
/// 机器码位长
/// 默认值6取值范围 [1, 15](要求:序列数位长+机器码位长不超过22
/// </summary>
public virtual byte WorkerIdBitLength { get; set; } = 6;//10;
/// <summary>
/// 序列数位长
/// 默认值6取值范围 [3, 21](要求:序列数位长+机器码位长不超过22
/// </summary>
public virtual byte SeqBitLength { get; set; } = 6;//10;
/// <summary>
/// 最大序列数(含)
/// 设置范围 [MinSeqNumber, 2^SeqBitLength-1]默认值0表示最大序列数取最大值2^SeqBitLength-1]
/// </summary>
public virtual int MaxSeqNumber { get; set; } = 0;
/// <summary>
/// 最小序列数(含)
/// 默认值5取值范围 [5, MaxSeqNumber]每毫秒的前5个序列数对应编号0-4是保留位其中1-4是时间回拨相应预留位0是手工新值预留位
/// </summary>
public virtual ushort MinSeqNumber { get; set; } = 5;
/// <summary>
/// 最大漂移次数(含),
/// 默认2000推荐范围500-10000与计算能力有关
/// </summary>
public virtual int TopOverCostCount { get; set; } = 2000;
/// <summary>
/// 数据中心ID默认0
/// </summary>
public virtual uint DataCenterId { get; set; } = 0;
/// <summary>
/// 数据中心ID长度默认0
/// </summary>
public virtual byte DataCenterIdBitLength { get; set; } = 0;
/// <summary>
/// 时间戳类型0-毫秒1-秒默认0
/// </summary>
public virtual byte TimestampType { get; set; } = 0;
public IdGeneratorOptions()
{
}
public IdGeneratorOptions(ushort workerId)
{
WorkerId = workerId;
}
}
}

View File

@ -0,0 +1,57 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Yitter.IdGenerator
{
/// <summary>
/// Id生成时回调参数
/// </summary>
public class OverCostActionArg
{
/// <summary>
/// 事件类型
/// 1-开始2-结束8-漂移
/// </summary>
public virtual int ActionType { get; set; }
/// <summary>
/// 时间戳
/// </summary>
public virtual long TimeTick { get; set; }
/// <summary>
/// 机器码
/// </summary>
public virtual ushort WorkerId { get; set; }
/// <summary>
/// 漂移计算次数
/// </summary>
public virtual int OverCostCountInOneTerm { get; set; }
/// <summary>
/// 漂移期间生产ID个数
/// </summary>
public virtual int GenCountInOneTerm { get; set; }
/// <summary>
/// 漂移周期
/// </summary>
public virtual int TermIndex { get; set; }
public OverCostActionArg(ushort workerId, long timeTick, int actionType = 0, int overCostCountInOneTerm = 0, int genCountWhenOverCost = 0, int index = 0)
{
ActionType = actionType;
TimeTick = timeTick;
WorkerId = workerId;
OverCostCountInOneTerm = overCostCountInOneTerm;
GenCountInOneTerm = genCountWhenOverCost;
TermIndex = index;
}
}
}

View File

@ -0,0 +1,379 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Yitter.IdGenerator
{
/// <summary>
/// 雪花漂移算法
/// </summary>
internal class SnowWorkerM1 : ISnowWorker
{
/// <summary>
/// 基础时间
/// </summary>
protected readonly DateTime BaseTime;
/// <summary>
/// 机器码
/// </summary>
protected readonly ushort WorkerId = 0;
/// <summary>
/// 机器码位长
/// </summary>
protected readonly byte WorkerIdBitLength = 0;
/// <summary>
/// 自增序列数位长
/// </summary>
protected readonly byte SeqBitLength = 0;
/// <summary>
/// 最大序列数(含)
/// </summary>
protected readonly int MaxSeqNumber = 0;
/// <summary>
/// 最小序列数(含)
/// </summary>
protected readonly ushort MinSeqNumber = 0;
/// <summary>
/// 最大漂移次数(含)
/// </summary>
protected int TopOverCostCount = 0;
protected byte _TimestampShift = 0;
protected static object _SyncLock = new object();
protected ushort _CurrentSeqNumber = 0;
protected long _LastTimeTick = 0; // -1L
protected long _TurnBackTimeTick = 0; // -1L;
protected byte _TurnBackIndex = 0;
protected bool _IsOverCost = false;
protected int _OverCostCountInOneTerm = 0;
#if DEBUG
protected int _GenCountInOneTerm = 0;
protected int _TermIndex = 0;
#endif
public Action<OverCostActionArg> GenAction { get; set; }
//private static long _StartTimeTick = 0;
//private static long _BaseTimeTick = 0;
public SnowWorkerM1(IdGeneratorOptions options)
{
// 1.BaseTime
if (options.BaseTime != DateTime.MinValue)
{
BaseTime = options.BaseTime;
}
// 2.WorkerIdBitLength
if (options.WorkerIdBitLength == 0)
{
WorkerIdBitLength = 6;
}
else
{
WorkerIdBitLength = options.WorkerIdBitLength;
}
// 3.WorkerId
WorkerId = options.WorkerId;
// 4.SeqBitLength
if (options.SeqBitLength == 0)
{
SeqBitLength = 6;
}
else
{
SeqBitLength = options.SeqBitLength;
}
// 5.MaxSeqNumber
if (options.MaxSeqNumber <= 0)
{
MaxSeqNumber = (1 << SeqBitLength) - 1;
}
else
{
MaxSeqNumber = options.MaxSeqNumber;
}
// 6.MinSeqNumber
MinSeqNumber = options.MinSeqNumber;
// 7.Others
TopOverCostCount = options.TopOverCostCount;
//if (TopOverCostCount == 0)
//{
// TopOverCostCount = 2000;
//}
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
_CurrentSeqNumber = options.MinSeqNumber;
//_BaseTimeTick = BaseTime.Ticks;
//_StartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount;
}
#if DEBUG
private void DoGenIdAction(OverCostActionArg arg)
{
//return;
Task.Run(() =>
{
GenAction(arg);
});
}
private void BeginOverCostAction(in long useTimeTick)
{
if (GenAction == null)
{
return;
}
DoGenIdAction(new OverCostActionArg(
WorkerId,
useTimeTick,
1,
_OverCostCountInOneTerm,
_GenCountInOneTerm,
_TermIndex));
}
private void EndOverCostAction(in long useTimeTick)
{
//if (_TermIndex > 10000)
//{
// _TermIndex = 0;
//}
if (GenAction == null)
{
return;
}
DoGenIdAction(new OverCostActionArg(
WorkerId,
useTimeTick,
2,
_OverCostCountInOneTerm,
_GenCountInOneTerm,
_TermIndex));
}
private void BeginTurnBackAction(in long useTimeTick)
{
if (GenAction == null)
{
return;
}
DoGenIdAction(new OverCostActionArg(
WorkerId,
useTimeTick,
8,
0,
0,
_TurnBackIndex));
}
private void EndTurnBackAction(in long useTimeTick)
{
if (GenAction == null)
{
return;
}
DoGenIdAction(new OverCostActionArg(
WorkerId,
useTimeTick,
9,
0,
0,
_TurnBackIndex));
}
#endif
protected virtual long NextOverCostId()
{
long currentTimeTick = GetCurrentTimeTick();
if (currentTimeTick > _LastTimeTick)
{
#if DEBUG
EndOverCostAction(currentTimeTick);
_GenCountInOneTerm = 0;
#endif
_LastTimeTick = currentTimeTick;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = false;
_OverCostCountInOneTerm = 0;
return CalcId(_LastTimeTick);
}
if (_OverCostCountInOneTerm >= TopOverCostCount)
{
#if DEBUG
EndOverCostAction(currentTimeTick);
_GenCountInOneTerm = 0;
#endif
// TODO: 在漂移终止,等待时间对齐时,如果发生时间回拨较长,则此处可能等待较长时间。可优化为:在漂移终止时增加时间回拨应对逻辑。(该情况发生概率低,暂不处理)
_LastTimeTick = GetNextTimeTick();
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = false;
_OverCostCountInOneTerm = 0;
return CalcId(_LastTimeTick);
}
if (_CurrentSeqNumber > MaxSeqNumber)
{
#if DEBUG
_GenCountInOneTerm++;
#endif
_LastTimeTick++;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = true;
_OverCostCountInOneTerm++;
return CalcId(_LastTimeTick);
}
#if DEBUG
_GenCountInOneTerm++;
#endif
return CalcId(_LastTimeTick);
}
protected virtual long NextNormalId()
{
long currentTimeTick = GetCurrentTimeTick();
if (currentTimeTick < _LastTimeTick)
{
if (_TurnBackTimeTick < 1)
{
_TurnBackTimeTick = _LastTimeTick - 1;
_TurnBackIndex++;
// 每毫秒序列数的前5位是预留位0用于手工新值1-4是时间回拨次序
// 支持4次回拨次序避免回拨重叠导致ID重复可无限次回拨次序循环使用
if (_TurnBackIndex > 4)
{
_TurnBackIndex = 1;
}
#if DEBUG
BeginTurnBackAction(_TurnBackTimeTick);
#endif
}
//Thread.Sleep(1);
return CalcTurnBackId(_TurnBackTimeTick);
}
// 时间追平时_TurnBackTimeTick清零
if (_TurnBackTimeTick > 0)
{
#if DEBUG
EndTurnBackAction(_TurnBackTimeTick);
#endif
_TurnBackTimeTick = 0;
}
if (currentTimeTick > _LastTimeTick)
{
_LastTimeTick = currentTimeTick;
_CurrentSeqNumber = MinSeqNumber;
return CalcId(_LastTimeTick);
}
if (_CurrentSeqNumber > MaxSeqNumber)
{
#if DEBUG
BeginOverCostAction(currentTimeTick);
_TermIndex++;
_GenCountInOneTerm = 1;
#endif
_OverCostCountInOneTerm = 1;
_LastTimeTick++;
_CurrentSeqNumber = MinSeqNumber;
_IsOverCost = true;
return CalcId(_LastTimeTick);
}
return CalcId(_LastTimeTick);
}
protected virtual long CalcId(long useTimeTick)
{
var result = ((useTimeTick << _TimestampShift) +
((long)WorkerId << SeqBitLength) +
(uint)_CurrentSeqNumber);
_CurrentSeqNumber++;
return result;
}
protected virtual long CalcTurnBackId(long useTimeTick)
{
var result = ((useTimeTick << _TimestampShift) +
((long)WorkerId << SeqBitLength) + _TurnBackIndex);
_TurnBackTimeTick--;
return result;
}
protected virtual long GetCurrentTimeTick()
{
//return (long)(DateTime.UtcNow - BaseTime).Ticks;
//return (long)(_StartTimeTick + Environment.TickCount);
return (long)(DateTime.UtcNow - BaseTime).TotalMilliseconds;
}
protected virtual long GetNextTimeTick()
{
long tempTimeTicker = GetCurrentTimeTick();
while (tempTimeTicker <= _LastTimeTick)
{
//Thread.Sleep(1);
SpinWait.SpinUntil(() => false, 1);
tempTimeTicker = GetCurrentTimeTick();
}
return tempTimeTicker;
}
public virtual long NextId()
{
lock (_SyncLock)
{
return _IsOverCost ? NextOverCostId() : NextNormalId();
}
}
}
}

View File

@ -0,0 +1,58 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Yitter.IdGenerator
{
/// <summary>
/// 常规雪花算法
/// </summary>
internal class SnowWorkerM2 : SnowWorkerM1
{
public SnowWorkerM2(IdGeneratorOptions options) : base(options)
{
}
public override long NextId()
{
lock (_SyncLock)
{
long currentTimeTick = GetCurrentTimeTick();
if (_LastTimeTick == currentTimeTick)
{
if (_CurrentSeqNumber++ > MaxSeqNumber)
{
_CurrentSeqNumber = MinSeqNumber;
currentTimeTick = GetNextTimeTick();
}
}
else
{
_CurrentSeqNumber = MinSeqNumber;
}
if (currentTimeTick < _LastTimeTick)
{
throw new Exception(string.Format("Time error for {0} milliseconds", _LastTimeTick - currentTimeTick));
}
_LastTimeTick = currentTimeTick;
var result = ((currentTimeTick << _TimestampShift) + ((long)WorkerId << SeqBitLength) + (uint)_CurrentSeqNumber);
return result;
}
}
}
}

View File

@ -0,0 +1,83 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Yitter.IdGenerator
{
/// <summary>
/// 雪花漂移算法支持数据中心ID和秒级时间戳
/// </summary>
internal class SnowWorkerM3 : SnowWorkerM1
{
/// <summary>
/// 数据中心ID默认0
/// </summary>
protected readonly uint DataCenterId = 0;
/// <summary>
/// 数据中心ID长度默认0
/// </summary>
protected readonly byte DataCenterIdBitLength = 0;
/// <summary>
/// 时间戳类型0-毫秒1-秒默认0
/// </summary>
protected readonly byte TimestampType = 0;
public SnowWorkerM3(IdGeneratorOptions options) : base(options)
{
// 秒级时间戳类型
TimestampType = options.TimestampType;
// DataCenter相关
DataCenterId = options.DataCenterId;
DataCenterIdBitLength = options.DataCenterIdBitLength;
if (TimestampType == 1)
{
TopOverCostCount = 0;
}
_TimestampShift = (byte)(DataCenterIdBitLength + WorkerIdBitLength + SeqBitLength);
}
protected override long CalcId(long useTimeTick)
{
var result = ((useTimeTick << _TimestampShift) +
((long)DataCenterId << DataCenterIdBitLength) +
((long)WorkerId << SeqBitLength) +
(long)_CurrentSeqNumber);
_CurrentSeqNumber++;
return result;
}
protected override long CalcTurnBackId(long useTimeTick)
{
var result = ((useTimeTick << _TimestampShift) +
((long)DataCenterId << DataCenterIdBitLength) +
((long)WorkerId << SeqBitLength) +
_TurnBackIndex);
_TurnBackTimeTick--;
return result;
}
protected override long GetCurrentTimeTick()
{
return TimestampType == 0 ?
(long)(DateTime.UtcNow - BaseTime).TotalMilliseconds :
(long)(DateTime.UtcNow - BaseTime).TotalSeconds;
}
}
}

View File

@ -0,0 +1,130 @@
/*
* yitter(yitter@126.com)
* https://github.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Yitter.IdGenerator
{
/// <summary>
/// 默认实现
/// </summary>
public class DefaultIdGenerator : IIdGenerator
{
private ISnowWorker _SnowWorker { get; set; }
//public Action<OverCostActionArg> GenIdActionAsync
//{
// get => _SnowWorker.GenAction;
// set => _SnowWorker.GenAction = value;
//}
public DefaultIdGenerator(IdGeneratorOptions options)
{
if (options == null)
{
throw new ArgumentException("options error.");
}
// 1.BaseTime
if (options.BaseTime < DateTime.Now.AddYears(-50) || options.BaseTime > DateTime.Now)
{
throw new ArgumentException("BaseTime error.");
}
// 2.WorkerIdBitLength
int maxLength = options.TimestampType == 0 ? 22 : 31; // 秒级时间戳时放大到31位
if (options.WorkerIdBitLength <= 0)
{
throw new ArgumentException("WorkerIdBitLength error.(range:[1, 21])");
}
if (options.DataCenterIdBitLength + options.WorkerIdBitLength + options.SeqBitLength > maxLength)
{
throw new ArgumentException("errorDataCenterIdBitLength + WorkerIdBitLength + SeqBitLength <= " + maxLength);
}
// 3.WorkerId & DataCenterId
var maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1;
if (maxWorkerIdNumber == 0)
{
maxWorkerIdNumber = 63;
}
if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber)
{
throw new ArgumentException("WorkerId error. (range:[0, " + maxWorkerIdNumber + "]");
}
var maxDataCenterIdNumber = (1 << options.DataCenterIdBitLength) - 1;
if (options.DataCenterId < 0 || options.DataCenterId > maxDataCenterIdNumber)
{
throw new ArgumentException("DataCenterId error. (range:[0, " + maxDataCenterIdNumber + "]");
}
// 4.SeqBitLength
if (options.SeqBitLength < 2 || options.SeqBitLength > 21)
{
throw new ArgumentException("SeqBitLength error. (range:[2, 21])");
}
// 5.MaxSeqNumber
var maxSeqNumber = (1 << options.SeqBitLength) - 1;
if (maxSeqNumber == 0)
{
maxSeqNumber = 63;
}
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber)
{
throw new ArgumentException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]");
}
// 6.MinSeqNumber
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber)
{
throw new ArgumentException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]");
}
// 7.TopOverCostCount
if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000)
{
throw new ArgumentException("TopOverCostCount error. (range:[0, 10000]");
}
switch (options.Method)
{
case 2:
_SnowWorker = new SnowWorkerM2(options);
break;
default:
if (options.DataCenterIdBitLength == 0 && options.TimestampType == 0)
{
_SnowWorker = new SnowWorkerM1(options);
}
else
{
_SnowWorker = new SnowWorkerM3(options);
}
break;
}
if (options.Method != 2)
{
Thread.Sleep(500);
}
}
public long NewLong()
{
return _SnowWorker.NextId();
}
}
}

View File

@ -0,0 +1,53 @@
/*
* yitter(yitter@126.com)
* https://gitee.com/yitter/idgenerator
* MIT
* 使
*
*
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Yitter.IdGenerator
{
/// <summary>
/// 这是一个调用的例子,默认情况下,单机集成者可以直接使用 NextId()。
/// </summary>
public class YitIdHelper
{
private static IIdGenerator _IdGenInstance = null;
public static IIdGenerator IdGenInstance => _IdGenInstance;
/// <summary>
/// 设置参数,建议程序初始化时执行一次
/// </summary>
/// <param name="options"></param>
public static void SetIdGenerator(IdGeneratorOptions options)
{
_IdGenInstance = new DefaultIdGenerator(options);
}
/// <summary>
/// 生成新的Id
/// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。
/// 否则将会初始化一个WorkerId为1的对象。
/// </summary>
/// <returns></returns>
public static long NextId()
{
if (_IdGenInstance == null)
{
_IdGenInstance = new DefaultIdGenerator(
new IdGeneratorOptions() { WorkerId = 1 }
);
}
return _IdGenInstance.NewLong();
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace Infrastructure.Test
{
class TestAutoMapper
{
[Test]
public void TestConvert()
{
var my = new MyClass
{
Name = "yubao"
};
var dest = my.MapTo<DestClass>();
Console.WriteLine(JsonHelper.Instance.Serialize(dest));
}
[Test]
public void TestConvertList()
{
var users = new List<MyClass> {
new MyClass {Name = "yubaolee1"}
, new MyClass{Name = "yubaolee2"}
};
var dest = users.MapToList<MyClass, DestClass>();
Console.WriteLine(JsonHelper.Instance.Serialize(dest));
var dest2 = users.MapToList<DestClass>();
Console.WriteLine(JsonHelper.Instance.Serialize(dest2));
}
}
class MyClass
{
public string Name { get; set; }
public string NickName { get; set; }
}
class DestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Linq.Expressions;
using NUnit.Framework;
namespace Infrastructure.Test
{
public class TestDynamicLinq
{
[Test]
public void Convert()
{
FilterGroup sub = new FilterGroup
{
Operation = "or"
};
sub.Filters = new[]
{
new Filter {Key = "name", Value = "name", Contrast = "=="},
new Filter {Key = "c3", Value = "10,20,30", Contrast = "in"}
};
FilterGroup filterGroup = new FilterGroup
{
Operation = "and"
};
filterGroup.Filters = new[]
{
new Filter {Key = "c1", Value = "name", Contrast = "contains"},
new Filter {Key = "10,20,30", Value = "40", Contrast = "intersect"}
};
filterGroup.Children = new[]
{
sub
};
var expression = DynamicLinq.ConvertGroup<TestOjb>(filterGroup,
Expression.Parameter(typeof(TestOjb), "c"));
Console.WriteLine(expression.ToString());
}
}
public class TestOjb{
public string c1 { get; set; }
public string c2 { get; set; }
public string c3 { get; set; }
public string c4 { get; set; }
public string c5 { get; set; }
public string c6 { get; set; }
public string c7 { get; set; }
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Yitter.IdGenerator;
namespace Infrastructure.Test
{
class TestSnowflake
{
[Test]
public void Generate()
{
// 全局初始化设置WorkerId默认最大2^16-1。初始化过程全局只需一次且必须最先设置
var options = new IdGeneratorOptions()
{
Method = 1,
WorkerId = 1
};
YitIdHelper.SetIdGenerator(options);
long newId = YitIdHelper.NextId();
Console.WriteLine("=====================================");
Console.WriteLine("生成的 Id" + newId);
}
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Infrastructure
{
public class TreeItem<T>
{
public T Item { get; set; }
public IEnumerable<TreeItem<T>> Children { get; set; }
}
}

View File

@ -0,0 +1,104 @@
using Infrastructure.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Utilities
{
public static class DESEncrypt
{
private static readonly string key = "hopetry###***";
//
// 摘要:
// 加密
//
// 参数:
// Text:
// 需要加密的内容
public static string Encrypt(string Text)
{
return Encrypt(Text, key);
}
//
// 摘要:
// 加密数据
//
// 参数:
// Text:
// 需要加密的内容
//
// sKey:
// 秘钥
public static string Encrypt(string Text, string sKey)
{
DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider();
byte[] bytes = Encoding.Default.GetBytes(Text);
dESCryptoServiceProvider.Key = Encoding.ASCII.GetBytes(Md5Helper.Hash(sKey).ToUpper().Substring(0, 8));
dESCryptoServiceProvider.IV = Encoding.ASCII.GetBytes(Md5Helper.Hash(sKey).ToUpper().Substring(0, 8));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, dESCryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(bytes, 0, bytes.Length);
cryptoStream.FlushFinalBlock();
StringBuilder stringBuilder = new StringBuilder();
byte[] array = memoryStream.ToArray();
foreach (byte b in array)
{
stringBuilder.AppendFormat("{0:X2}", b);
}
return stringBuilder.ToString();
}
//
// 摘要:
// 解密
//
// 参数:
// Text:
// 需要解密的内容
public static string Decrypt(string Text)
{
if (!string.IsNullOrEmpty(Text))
{
return Decrypt(Text, key);
}
return "";
}
//
// 摘要:
// 解密数据
//
// 参数:
// Text:
// 需要解密的内容
//
// sKey:
// 秘钥
public static string Decrypt(string Text, string sKey)
{
DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider();
int num = Text.Length / 2;
byte[] array = new byte[num];
for (int i = 0; i < num; i++)
{
int num2 = Convert.ToInt32(Text.Substring(i * 2, 2), 16);
array[i] = (byte)num2;
}
dESCryptoServiceProvider.Key = Encoding.ASCII.GetBytes(Md5Helper.Hash(sKey).ToUpper().Substring(0, 8));
dESCryptoServiceProvider.IV = Encoding.ASCII.GetBytes(Md5Helper.Hash(sKey).ToUpper().Substring(0, 8));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, dESCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(array, 0, array.Length);
cryptoStream.FlushFinalBlock();
return Encoding.Default.GetString(memoryStream.ToArray());
}
}
}

View File

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
namespace Infrastructure.Utilities
{
/// <summary>
/// 动态属性Bag
/// </summary>
public class DynamicPropertyBag : DynamicObject
{
private Dictionary<string, object> storage = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (storage.ContainsKey(binder.Name))
{
result = storage[binder.Name];
return true;
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
string key = binder.Name;
if (storage.ContainsKey(key))
storage[key] = value;
else
storage.Add(key, value);
return true;
}
public override string ToString()
{
StringWriter message = new StringWriter();
foreach (var item in storage)
message.WriteLine("{0}:\t{1}", item.Key, item.Value);
return message.ToString();
}
}
}

Some files were not shown because too many files have changed in this diff Show More