日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

.net项目的二次开发解决方案

發布時間:2025/7/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .net项目的二次开发解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

公司原來項目的二次開發方式主要使用SQL,基本上也能滿足客戶的要求,優點是使用簡單,只要熟悉SQL語句就可以操作,缺點是受限制太多,需要對數據庫底層相當的了解,使用時容易出錯,無法直接調用業務層代碼等,研究了一下.net的動態編譯,感覺用它來做二次開發效果應該不錯的。
首先我們先做個demo來解釋一下動態編譯,下面這段代碼的意思就是先組織一個源碼字符串,然后編譯執行。

?

動態編譯簡單代碼
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Reflection;
using?System.CodeDom.Compiler;
using?Microsoft.CSharp;

namespace?ConsoleApplication6
{
????
class?Program
????{
????????
//C#代碼提供者
????????private?static?CodeDomProvider?comp?=?new?CSharpCodeProvider();
????????
//用于調用編譯器的參數
????????private?static?CompilerParameters?cp?=?new?CompilerParameters();
????????
private?static?MethodInfo?mi;
????????
static?void?Main(string[]?args)
????????{
????????????StringBuilder?codeBuilder?
=?new?StringBuilder();
????????????codeBuilder.AppendLine(
"using?System;");
????????????codeBuilder.AppendLine(
"public?class?MyClass");
????????????codeBuilder.AppendLine(
"{");
????????????codeBuilder.AppendLine(
"public??void?hello()");
????????????codeBuilder.AppendLine(
"{");
????????????codeBuilder.AppendLine(
"Console.WriteLine(?\"hello\");");
????????????codeBuilder.AppendLine(
"}");
????????????codeBuilder.AppendLine(
"}");
????????????
//加入需要引用的程序集
????????????cp.ReferencedAssemblies.Add("System.dll");?
????????????CompilerResults?cr?
=?comp.CompileAssemblyFromSource(cp,?codeBuilder.ToString());
????????????
//如果有編譯錯誤
????????????if?(cr.Errors.HasErrors)
????????????{
????????????????
foreach?(CompilerError?item?in?cr.Errors)
????????????????{
????????????????????Console.WriteLine(item.ToString());?
????????????????}
????????????}
????????????
else
????????????{
????????????????Assembly?a?
=?cr.CompiledAssembly;???//獲取已編譯的程序集
????????????????Type?t?=?a.GetType("MyClass");??????//利用反射獲得類型
????????????????object?mode?=?a.CreateInstance("MyClass");
????????????????mi?
=?t.GetMethod("hello",?BindingFlags.Instance?|?BindingFlags.Public);
????????????????mi.Invoke(mode,?
new?object[0]);?????//執行方法
????????????}
????????}
????}
}

?

了解了上面這段代碼,我們基本對動態編譯的概念清楚了,但是如果在項目中這樣使用的話,我們要自己去控制源代碼的全部文檔內容,如果大規模應用的話會非常的麻煩,需要重復編寫命名空間構造,類構造,函數構造等,如果我們還想看到一個格式良好的源碼,我們還必須自己控制格式。現在我們來介紹一種源碼構造方式來解決這些問題,請看如下代碼:

?

動態編譯簡單代碼改進
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Reflection;
using?System.CodeDom.Compiler;
using?Microsoft.CSharp;
using?System.CodeDom;
using?System.IO;

namespace?ConsoleApplication6
{
????
class?Program
????{

????????
static?void?Main(string[]?args)
????????{
????????????Console.WriteLine(GenerateCode(
"Hello","Hello","\t\t\treturn?\"hello\";"));
????????}
????????
public?static?CodeCompileUnit?CreateExecutionClass(string?typeNamespace,
????????????
string?typeName,string?scriptBody)
????????{
????????????
//?創建CodeCompileUnit以包含代碼
????????????CodeCompileUnit?ccu?=?new?CodeCompileUnit();?
????????????
//?分配需要的命名空間?
????????????CodeNamespace?cns?=?new?CodeNamespace(typeNamespace);
????????????cns.Imports.Add(
new?CodeNamespaceImport("System"));
????????????ccu.Namespaces.Add(cns);?
????????????
//?創建新的類聲明
????????????CodeTypeDeclaration?parentClass?=?new?CodeTypeDeclaration(typeName);
????????????cns.Types.Add(parentClass);?
????????????
//?創建獲得一個參數并返回一個字符串的Hello方法
????????????CodeMemberMethod?method?=?new?CodeMemberMethod();
????????????method.Name?
=?"Hello";
????????????method.Attributes?
=?MemberAttributes.Public;
????????????CodeParameterDeclarationExpression?arg?
=?new?CodeParameterDeclarationExpression(typeof(string),?"inputMessage");
????????????method.Parameters.Add(arg);
????????????method.ReturnType?
=?new?CodeTypeReference(typeof(string));?
????????????
//?添加方法實體需要的代碼
????????????CodeSnippetStatement?methodBody?=?new?CodeSnippetStatement(scriptBody);
????????????method.Statements.Add(methodBody);
????????????parentClass.Members.Add(method);?
????????????
return?ccu;
????????}
????????
public?static?string?GenerateCode(string?typeNamespace,
????????????
string?typeName,string?scriptBody)
????????{
????????????
//?調用我們前面的方法創建CodeCompileUnit
????????????CodeCompileUnit?ccu?=?CreateExecutionClass(typeNamespace,
????????????typeName,?scriptBody);?CSharpCodeProvider?provider?
=?new?CSharpCodeProvider();
????????????CodeGeneratorOptions?options?
=?new?CodeGeneratorOptions();
????????????options.BlankLinesBetweenMembers?
=?false;
????????????options.IndentString?
=?"\t";//指定縮進字符
????????????options.BracingStyle?=?"C";//大括號換行
????????????StringWriter?sw?=?new?StringWriter();
????????????
try
????????????{
????????????????provider.GenerateCodeFromCompileUnit(ccu,?sw,?options);
????????????????sw.Flush();
????????????}
????????????
finally
????????????{
????????????????sw.Close();
????????????}?
????????????
return?sw.GetStringBuilder().ToString();
????????}

????}
}

?

執行結果如下:


大家了解了動態編譯之后,我們這里介紹一個稍微復雜一點的應用:
需求:我們先預定義一個執行流程,而具體執行代碼可以在我們項目部署之后再編寫。比如說工資的計算在不同應用中算法會有很大的不同。
我們首先定義一個數據庫中的數據結構:

?

然后將這個表拖入到dbml(生成的dbml文件請下載源碼)文件中,現在我們就開始編寫相應的代碼吧:
首先我們先來處理函數的參數,如果我們只是將參數列表的字符串存入數據庫中的話,我們還要根據格式序列化和反序列化這個參數,所以我們使用

xml存入sqlserver2005中,格式如下

參數格式
<Parameters>
??
<Parameter>
????
<Type>System.String</Type>
????
<ParameterName>inputMessage</ParameterName>
??
</Parameter>
??
<Parameter>
????
<Type>System.Int32</Type>
????
<ParameterName>inputInt</ParameterName>
??
</Parameter>
</Parameters>

為了方便起見我們在這里定義一個FunctionScript的分布類來處理參數問題

?

參數處理
namespace?Phenix.DynamicCompiler
{
????
public?partial?class?FunctionScript
????{
????????
///?<summary>
????????
///?返回參數列表
????????
///?</summary>
????????
///?<returns></returns>
????????public?List<CodeParameterDeclarationExpression>?GetParameterList()
????????{
????????????List
<CodeParameterDeclarationExpression>?parameterList?=?new?List<CodeParameterDeclarationExpression>();
????????????
if?(this.Parameters!=null)
????????????{
????????????????var?x?
=?from?n?in?this.Parameters.Elements("Parameter")
????????????????????????select?n;
????????????????
foreach?(var?item?in?x)
????????????????{
????????????????????parameterList.Add(
new?CodeParameterDeclarationExpression(
????????????????????????Type.GetType((
string)item.Element("Type")),
????????????????????????(
string)item.Element("ParameterName")));

????????????????}
????????????????
????????????}
???????????
????????????
return?parameterList;
????????}
????}
}

?

然后我們需要一個代碼構造類,用于根據情況構造代碼:

?

代碼構造類
namespace?Phenix.DynamicCompiler
{
????
public?class?CodeBuilder
????{
????????StringCollection?importNameSpace;
????????List
<FunctionScript>?functionScriptList;
????????
string?typeNamespace;
????????
string?className;

????????
///?<summary>
????????
///?
????????
///?</summary>
????????
///?<param?name="importNameSpace">導入命名空間</param>
????????
///?<param?name="className">類名</param>
????????
///?<param?name="functionInfoList">函數列表</param>
????????public?CodeBuilder(StringCollection?importNameSpace,string?typeNamespace,string?className,
????????????List
<FunctionScript>?functionScriptList)
????????{
????????????
if?(functionScriptList?==?null?||?functionScriptList.Count==0)
????????????{
????????????????
throw?new?Exception("函數列表不能為空");
????????????}
????????????
this.importNameSpace?=?importNameSpace;
????????????
this.typeNamespace?=?typeNamespace;
????????????
this.className?=?className;
????????????
this.functionScriptList?=?functionScriptList;
????????????
if?(functionScriptList.GroupBy(c?=>?c.ClassName).Count()?>?1)
????????????{
????????????????
throw?new?Exception("這些函數不屬于一個類");
????????????}

????????}
????????
public?CodeBuilder(string?typeNamespace,string?className,
????????????List
<FunctionScript>?functionScriptList):this(?null,typeNamespace,className,functionScriptList)
????????{

????????}
????????
public?CodeBuilder(List<FunctionScript>?functionScriptList):
????????????
this(functionScriptList.Count==0?null:functionScriptList[0].ClassNameSpace,
????????????functionScriptList.Count?
==?0???null?:?functionScriptList[0].ClassName,
????????????functionScriptList)
????????{
????????}
????????
private??CodeCompileUnit?CreateExecutionClass()
????????{
????????????
//?創建CodeCompileUnit以包含代碼
????????????CodeCompileUnit?ccu?=?new?CodeCompileUnit();?//?分配需要的命名空間?
????????????CodeNamespace?cns?=?new?CodeNamespace(typeNamespace);
????????????cns.Imports.Add(
new?CodeNamespaceImport("System"));
????????????ccu.Namespaces.Add(cns);?
//?創建新的類聲明
????????????CodeTypeDeclaration?codeClass?=?new?CodeTypeDeclaration(className);
????????????cns.Types.Add(codeClass);?
//?在命名空間下加入類
????????????foreach?(var?functionScript?in?functionScriptList)
????????????{
????????????????CodeMemberMethod?method?
=?new?CodeMemberMethod();
????????????????method.Name?
=?functionScript.FunctionName;
????????????????
//方法的訪問標識符為public?static
????????????????method.Attributes?=?MemberAttributes.Static?|?MemberAttributes.Public;
????????????????
foreach?(var?parameter?in?functionScript.GetParameterList())
????????????????{
????????????????????method.Parameters.Add(parameter);
????????????????}

????????????????
if?(functionScript.ReturnType?!=?null)
????????????????{
????????????????????method.ReturnType?
=?new?CodeTypeReference(Type.GetType(functionScript.ReturnType));?
??
????????????????}
????????????????
//?添加方法實體需要的代碼
????????????????CodeSnippetStatement?methodBody?=?new?CodeSnippetStatement(functionScript.ScriptBody);
????????????????method.Statements.Add(methodBody);

????????????????codeClass.Members.Add(method);?

????????????}
????????????
return?ccu;
????????}
????????
public??string?GenerateCode()
????????{
????????????
//?調用我們前面的方法創建CodeCompileUnit
????????????CodeCompileUnit?ccu?=?CreateExecutionClass();
????????????CSharpCodeProvider?provider?
=?new?CSharpCodeProvider();
????????????CodeGeneratorOptions?options?
=?new?CodeGeneratorOptions();
????????????options.BlankLinesBetweenMembers?
=?false;
????????????options.BracingStyle?
=?"C";//大括號換行
????????????options.IndentString?=?"\t";
????????????StringWriter?sw?
=?new?StringWriter();
????????????
try
????????????{
????????????????provider.GenerateCodeFromCompileUnit(ccu,?sw,?options);
????????????????sw.Flush();
????????????}
????????????
finally
????????????{
????????????????sw.Close();
????????????}
????????????
return?sw.GetStringBuilder().ToString();
????????}
????}
}

?

下面我們再編寫一個用于編譯的類:

?

編譯類
namespace?Phenix.DynamicCompiler
{
????
public?class?PhenixCompiler
????{
????????
///?<summary>
????????
///?編譯
????????
///?</summary>
????????
///?<param?name="codeString">需要編譯的代碼</param>
????????
///?<param?name="outputAssembly">輸出程序集位置</param>
????????public?void?Compile(string?codeString,?string?outputAssembly)
????????{
????????????CompilerParameters?compilerParams?
=?new?CompilerParameters();
????????????
///編譯器選項設置
????????????compilerParams.CompilerOptions?=?"/target:library?/optimize";

????????????compilerParams.OutputAssembly?
=?outputAssembly;
????????????
///生成調試信息
????????????compilerParams.IncludeDebugInformation?=?false;

????????????
///添加相關的引用
????????????foreach?(var?item?in?ReferencedAssemblies)
????????????{
????????????????compilerParams.ReferencedAssemblies.Add(item);
????????????}

????????????CSharpCodeProvider?provider?
=?new?CSharpCodeProvider();

????????????
///編譯
????????????CompilerResults?results?=?provider.CompileAssemblyFromSource(compilerParams,?codeString);
????????????
if?(results.Errors.HasErrors)
????????????{
????????????????StringBuilder?errors?
=?new?StringBuilder();
????????????????
foreach?(CompilerError?item?in?results.Errors)
????????????????{
????????????????????errors.AppendLine(item.ToString());
????????????????}
????????????????
throw?new?Exception(errors.ToString());
????????????}
????????????
///創建程序集
????????????Assembly?asm?=?results.CompiledAssembly;


????????}
????????
private?StringCollection?ReferencedAssemblies
????????{?
get;?set;?}
????????
public?PhenixCompiler(StringCollection?referencedAssemblies)
????????{
????????????ReferencedAssemblies?
=?referencedAssemblies;
????????????ReferencedAssemblies.Add(
"mscorlib.dll");
????????????ReferencedAssemblies.Add(
"System.dll");
????????}
????????
public?PhenixCompiler()
????????????:?
this(new?StringCollection())
????????{?}
????}
}

?

我們再構造一個用于執行的類:

執行類
namespace?DynamicCompiler
{
????
public?class?Executor
????{
????????
string?inputAssembly;
????????
string?instanceName;
????????
string?methodName;
????????
public?void?Execute()
????????{
????????????Assembly?assembly?
=?Assembly.LoadFrom(inputAssembly);
????????????MethodInfo?mi;
????????????Type?t?
=?assembly.GetType(instanceName);
????????????
object?mode?=?assembly.CreateInstance(instanceName);
????????????mi?
=?t.GetMethod(methodName,?BindingFlags.Static?|?BindingFlags.Public);
????????????mi.Invoke(mode,?
new?object[0]);?
????????}
????????
public?Executor(string?inputAssembly,string?instanceName,string?methodName)
????????{
????????????
this.inputAssembly?=?inputAssembly;
????????????
this.instanceName?=?instanceName;
????????????
this.methodName?=?methodName;
????????}
????}
}

?

主函數代碼如下:

?

主程序
class?Program
????{
????????
const?string?functionIndentSpace?=?"\t\t\t";
????????
static?void?Main(string[]?args)
????????{
????????????XElement?f1parameter?
=?new?XElement("Parameters",
????????????????
new?XElement("Parameter",
????????????????
new?XElement("Type",?"System.String"),
????????????????
new?XElement("ParameterName",?"inputMessage")),
????????????????
new?XElement("Parameter",
????????????????
new?XElement("Type",?"System.Int32"),
????????????????
new?XElement("ParameterName",?"inputInt"))
????????????????);
????????????
????????????FunctionScript?f1?
=?new?FunctionScript()?
????????????{?
????????????????ClassName?
=?"MyClass",?
????????????????ClassNameSpace?
=?"My",?
????????????????FunctionName?
=?"hello",
????????????????ReturnType
="System.String",
????????????????Parameters
=f1parameter,
????????????????ScriptBody?
=?functionIndentSpace+"return?\"hello\"+inputInt.ToString();"?
????????????};
????????????FunctionScript?f2?
=?new?FunctionScript()
????????????{
????????????????ClassName?
=?"MyClass",
????????????????ClassNameSpace?
=?"My",
????????????????FunctionName?
=?"hello1",
????????????????ScriptBody?
=?functionIndentSpace?+?"Console.WriteLine(hello(\"x\",1));"
????????????};
????????????List
<FunctionScript>?list=new?List<FunctionScript>();
????????????list.Add(f1);
????????????list.Add(f2);
????????????CodeBuilder?c?
=?new?CodeBuilder(list);
????????????Console.WriteLine(c.GenerateCode());
????????????Compiler?pc?
=?new?Compiler();
????????????pc.Compile(c.GenerateCode(),?
"x.dll");

????????????Executor?ex?
=?new?Executor("x.dll",?"My.MyClass",?"hello1");
????????????ex.Execute();

????????}
????}

?

運行結果如下

這里邊工作的四個對象的時序圖如下:

源碼下載

在項目中應用可以結合http://www.cnblogs.com/nuaalfm/archive/2008/09/08/1286640.html中的插件編程

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的.net项目的二次开发解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。