动态创建类文件
动态创建类文件后,就可以使用上一篇文章[小技巧]C# .net 动态编程 (1)中的动态编译生成动态的对象了。这样就方便多了。
知识点
效果
通过类动态生成cs类
就是写文件操作,为什么这样做呢,这让我联想到了WCF引用自动生成代码的东西。
以下是自动生成的类
//------------------------------------------------------------------------------// <auto-generated>// 此代码由工具生成。// 运行时版本:4.0.30319.42000//// 对此文件的更改可能会导致不正确的行为,并且如果// 重新生成代码,这些更改将会丢失。// </auto-generated>//------------------------------------------------------------------------------namespace Test{using System;using System.Collections.Generic;public partial class Test{/// <summary>/// A/// </summary>private int A;/// <summary>/// b/// </summary>private string b;/// <summary>/// bList/// </summary>private System.Collections.Generic.List<string> bList;/// <summary>/// B/// </summary>public virtual string B{get{return this.b;}set{this.b = value;}}/// <summary>/// BList/// </summary>public virtual System.Collections.Generic.List<string> BList{get{return this.bList;}set{this.bList = value;}}}}
调用方式
ClassCreator creator = new ClassCreator();creator.AddFields("A", typeof(int));creator.AddFields("A", typeof(string));creator.AddProperties("B", typeof(string));creator.AddProperties("BList", typeof(List<string>));if (creator.GenerateCode("Test", "Test"))Console.WriteLine("Success");elseConsole.WriteLine("Failed");
创建类的源代码
using System;using System.CodeDom;using System.CodeDom.Compiler;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.Text;namespace 动态编程{public class ClassCreator{/// <summary>/// Define the compile unit to use for code generation./// </summary>private CodeCompileUnit targetUnit;/// <summary>/// The only class in the compile unit. This class contains 2 fields,/// 3 properties, a constructor, an entry point, and 1 simple method./// </summary>private CodeTypeDeclaration targetClass;private List<string> namespaceNames;/// <summary>/// 字段/// </summary>private List<CodeMemberField> codeMemberFields;/// <summary>/// 属性/// </summary>private List<CodeMemberProperty> codeMemberPropertys;/// <summary>/// Define the class./// </summary>public ClassCreator(){namespaceNames = new List<string>();codeMemberFields = new List<CodeMemberField>();codeMemberPropertys = new List<CodeMemberProperty>();}/// <summary>/// 添加字段/// </summary>/// <param name="fileName">字段名称</param>/// <param name="type">字段类型</param>/// <param name="visitLevel">访问级别 默认是private</param>/// <param name="comments">字段描述信息</param>public void AddFields(string fileName, Type type, MemberAttributes visitLevel = MemberAttributes.Private, string comments = null){if (codeMemberFields.Exists(t => t.Name == fileName)) return;CodeMemberField field = new CodeMemberField();field.Attributes = visitLevel;field.Name = fileName;field.Type = new CodeTypeReference(type);field.Comments.Add(new CodeCommentStatement(" <summary>", true));field.Comments.Add(new CodeCommentStatement(comments ?? fileName, true));field.Comments.Add(new CodeCommentStatement(" </summary>", true));codeMemberFields.Add(field);AddNamespance(type);}/// <summary>/// 添加属性/// </summary>/// <param name="propertyName">属性名称</param>/// <param name="type">属性类型</param>/// <param name="comments">属性描述信息</param>public void AddProperties(string propertyName, Type type, bool hasGet = true, bool hasSet = true, string comments = null){if (codeMemberPropertys.Exists(t => t.Name == propertyName)) return;CodeMemberProperty property = new CodeMemberProperty();property.Attributes = MemberAttributes.Public;property.Name = propertyName;property.HasGet = hasGet;property.HasSet = hasSet;property.Type = new CodeTypeReference(type);property.Comments.Add(new CodeCommentStatement(" <summary>", true));property.Comments.Add(new CodeCommentStatement(comments ?? propertyName, true));property.Comments.Add(new CodeCommentStatement(" </summary>", true));var fileName = (propertyName[0]).ToString().ToLower() + propertyName.Substring(1);if (!codeMemberFields.Exists(t => t.Name == fileName))AddFields(fileName, type, MemberAttributes.Private, comments);property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fileName)));CodeFieldReferenceExpression reference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fileName);property.SetStatements.Add(new CodeAssignStatement(reference, new CodeArgumentReferenceExpression("value")));codeMemberPropertys.Add(property);AddNamespance(type);}private void AddNamespance(Type type){if (namespaceNames.IndexOf(type.Namespace) == -1)namespaceNames.Add(type.Namespace);}/// <summary>/// 生成代码/// </summary>/// <param name="namespaceName">命名空间</param>/// <param name="className">类型</param>/// <param name="visitLevel">访问级别,默认是Public</param>/// <param name="filePath">文件完整路径,默认是程序所在目录,和类名同名</param>/// <returns>true | false</returns>public bool GenerateCode(string namespaceName, string className, TypeAttributes visitLevel = TypeAttributes.Public, string filePath = null){try{targetUnit = new CodeCompileUnit();CodeNamespace newClass = new CodeNamespace(namespaceName);targetClass = new CodeTypeDeclaration(className);targetClass.IsClass = true;targetClass.TypeAttributes = visitLevel;targetClass.IsPartial = true;newClass.Types.Add(targetClass);targetUnit.Namespaces.Add(newClass);namespaceNames.ForEach(item =>{newClass.Imports.Add(new CodeNamespaceImport(item));});codeMemberFields.ForEach(item =>{targetClass.Members.Add(item);});codeMemberPropertys.ForEach(item =>{targetClass.Members.Add(item);});CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");CodeGeneratorOptions options = new CodeGeneratorOptions();options.BracingStyle = "C";using (StreamWriter sourceWriter = new StreamWriter(filePath ?? $"{className}.cs")){provider.GenerateCodeFromCompileUnit(targetUnit, sourceWriter, options);}return true;}catch (Exception){return false;}}}}
测试代码
Test.Test t = new Test.Test() { B="aaaa"};Console.WriteLine(t.B);
运行效果
总结
可以生成代码了,再根据上一篇的内容动态编译,一定可以实现动态编程的。
注:下一篇试下以下结合使用
https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/how-to-create-a-class-using-codedom
————————————————
版权声明:本文为CSDN博主「iml6yu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/iml6yu/article/details/119858749
