动态创建类文件
动态创建类文件后,就可以使用上一篇文章[小技巧]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");
else
Console.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