Net5和NetCore可用
嗯,这里就是最后一章了,至于为什么是红字,就是为了和前面假装同意一点,啊哈哈哈
先上源码,900多行,我折叠了,具体怎么用看后面讲解。
public class CodeMake
{
#region Field Area
private CodeNamespace _samples;
private CodeCompileUnit _targetUnit;
private CodeTypeDeclaration _targetClass;
private readonly string _outputFileName;
private static IList<string> _assemblyUsingLocation = null;
private event Action _assemblyLoad = null;
/// <summary>
/// 单例IOC容器
/// </summary>
private static Dictionary<string, object> _singletonContainer = null;
private static readonly object _lock_obj = new object();
/// <summary>
/// 命名空间
/// </summary>
public string NameSpace { get; private set; }
/// <summary>
/// 类名称
/// </summary>
public string ClassName { get; private set; }
/// <summary>
/// 命名空间+类名称
/// </summary>
public string FullNameSpaceWithClass { get; private set; }
#region CodeMaker Filter 节点
private static bool _onecEventNotRun = true;
/// <summary>
/// 整个项目运行中只调用一次的事件,事件发生点在尚未构造对象之前
/// </summary>
public event Action DoOnceWorkBeforeConstructor = null;
/// <summary>
/// 开始构造函数之前
/// </summary>
public event Action BeforeConstructor = null;
/// <summary>
/// 结束构造函数时
/// </summary>
public event Action AfterConstructor = null;
/// <summary>
/// 添加命名空间之前(生成代码 AddNamespace)
/// </summary>
public event Action BeforeAddNamespace = null;
/// <summary>
/// 添加命名空间之后(生成代码 AddNamespace)
/// </summary>
public event Action AfterAddNamespace = null;
/// <summary>
/// 添加构造函数之前(生成代码 AddConstructor)
/// </summary>
public event Action BeforeAddConstructor = null;
/// <summary>
/// 添加构造函数之后(生成代码 AddConstructor)
/// </summary>
public event Action AfterAddConstructor = null;
/// <summary>
/// 添加字段之前(生成代码 AddField)
/// </summary>
public event Action BeforeAddField = null;
/// <summary>
/// 添加字段之后(生成代码 AddField)
/// </summary>
public event Action AfterAddField = null;
/// <summary>
/// 添加属性之前(生成代码 AddPropertie)
/// </summary>
public event Action BeforeAddPropertie = null;
/// <summary>
/// 添加属性之后(生成代码 AddPropertie)
/// </summary>
public event Action AfterAddPropertie = null;
/// <summary>
/// 添加方法之前(生成代码 AddMethod)
/// </summary>
public event Action BeforeAddMethod = null;
/// <summary>
/// 添加方法之后(生成代码 AddMethod)
/// </summary>
public event Action AfterAddMethod = null;
/// <summary>
/// 创建对象之前(生成实例 CreateInstance)
/// </summary>
public event Action BeforeCreateInstance = null;
/// <summary>
/// 创建对象之后(生成实例 CreateInstance)
/// </summary>
public event Action AfterCreateInstance = null;
#endregion
#endregion
#region Ctor
static CodeMake()
{
if (_singletonContainer is null)
{
lock (_lock_obj)
{
if (_singletonContainer is null)
{
_singletonContainer = new Dictionary<string, object>();
}
}
}
if (_assemblyUsingLocation is null)
{
lock (_lock_obj)
{
if (_assemblyUsingLocation is null)
{
_assemblyUsingLocation = new List<string>();
}
}
}
}
public CodeMake(bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
: this("CodeDOM", reLoadAssembly, eventCallBack)
{
}
public CodeMake(string nameSpace, bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
: this(nameSpace, "System", reLoadAssembly, eventCallBack)
{
}
public CodeMake(string nameSpace, string usingNameSpace, bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
: this(nameSpace, usingNameSpace, "CreatedClass", reLoadAssembly, eventCallBack)
{
}
public CodeMake(string nameSpace, string usingNameSpace, string className, bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
: this(nameSpace, usingNameSpace, className, TypeAttributes.Public, reLoadAssembly, eventCallBack)
{
}
public CodeMake(string nameSpace, string usingNameSpace, string className, TypeAttributes visitAttr, bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
: this(nameSpace, usingNameSpace, className, visitAttr, "C:\\", reLoadAssembly, eventCallBack)
{
}
public CodeMake(string nameSpace, string usingNameSpace, string className, TypeAttributes visitAttr, string fileFullPath, bool reLoadAssembly = false, Action<CodeMake> eventCallBack = null)
{
#region Verify Area
if (string.IsNullOrEmpty(nameSpace))
{
throw new ArgumentException("命名空间不能为空");
}
if (string.IsNullOrEmpty(className))
{
throw new ArgumentException("类名不能为空");
}
#endregion
if (eventCallBack != null)
{
eventCallBack(this);
}
if (_onecEventNotRun)
{
if (DoOnceWorkBeforeConstructor != null)
{
DoOnceWorkBeforeConstructor();
_onecEventNotRun = false;
}
}
if (BeforeConstructor != null)
{
BeforeConstructor();
}
#region Main
if (_assemblyUsingLocation.Count <= 0)
{
_assemblyLoad += () => LoadBasicAssembly();
}
if (reLoadAssembly)
{
_assemblyLoad += () => LoadBasicAssembly();
}
_targetUnit = new CodeCompileUnit();
_samples = new CodeNamespace(nameSpace);
_samples.Imports.Add(new CodeNamespaceImport(usingNameSpace));
_targetClass = new CodeTypeDeclaration(className);
_targetClass.IsClass = true;
_targetClass.TypeAttributes = visitAttr;
_samples.Types.Add(_targetClass);
_targetUnit.Namespaces.Add(_samples);
NameSpace = nameSpace;
ClassName = className;
FullNameSpaceWithClass = NameSpace + "." + ClassName;
_outputFileName = fileFullPath;
#endregion
if (AfterConstructor != null)
{
AfterConstructor();
}
}
#endregion
#region AssemblyLoadLocation Function Area
/// <summary>
/// 基础程序集加载
/// </summary>
private void LoadBasicAssembly()
{
if (_assemblyUsingLocation.Count > 0)
{
_assemblyUsingLocation.Clear();
}
DirectoryInfo root1 = new DirectoryInfo(AppContext.BaseDirectory);
foreach (FileInfo f in root1.GetFiles())
{
if (f.Name.Contains(".dll", StringComparison.OrdinalIgnoreCase))
{
AddedAssemblyBy(f.FullName);
}
}
AddedAssemblyBy(typeof(System.Object).GetTypeInfo().Assembly.Location);
AddedAssemblyBy(typeof(Console).GetTypeInfo().Assembly.Location);
AddedAssemblyBy(Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), "System.Runtime.dll"));
}
/// <summary>
/// 加载程序集
/// </summary>
/// <param name="location"></param>
private void AddedAssemblyBy(string location)
{
if (!_assemblyUsingLocation.Any(s => s.Contains(location)))
{
_assemblyUsingLocation.Add(location);
}
}
/// <summary>
/// 自定义一个生成对象引用的程序集扩展
/// </summary>
/// <param name="assemblyLocations"></param>
/// <returns></returns>
public CodeMake AddAssembly(string assemblyLocation)
=> AddAssemblys(new List<string> { assemblyLocation });
/// <summary>
/// 自定义一组生成对象引用的程序集扩展
/// </summary>
/// <param name="assemblyLocations"></param>
/// <returns></returns>
public CodeMake AddAssemblys(List<string> assemblyLocations)
{
foreach (var location in assemblyLocations)
{
_assemblyLoad += () => AddedAssemblyBy(location);
}
return this;
}
#endregion
#region NameSpaceAdded Function Area
/// <summary>
/// 新增命名空间
/// </summary>
/// <param name="codeNamespaceImport">命名空间文本,不需要添加using</param>
public CodeMake AddNamespace(string codeNamespaceImport)
=> AddNamespaces(() => new List<CodeNamespaceImport> { new CodeNamespaceImport(codeNamespaceImport) });
/// <summary>
/// 新增多个命名空间
/// </summary>
/// <param name="codeNamespaceImport">命名空间文本,不需要添加using</param>
public CodeMake AddNamespaces(List<string> codeNamespaceImport)
{
List<CodeNamespaceImport> codeNamespace = new List<CodeNamespaceImport>();
codeNamespaceImport.ForEach(c => codeNamespace.Add(new CodeNamespaceImport(c)));
return AddNamespaces(() => codeNamespace);
}
/// <summary>
/// 新增命名空间 自定义
///
/// Demo
/// var codeNamespace = new CodeNamespaceImport>("namespace");
/// </summary>
/// <param name="codeNamespaceImport"></param>
public CodeMake AddNamespace(Func<CodeNamespaceImport> codeNamespaceImport)
=> AddNamespaces(() => new List<CodeNamespaceImport> { codeNamespaceImport() });
/// <summary>
/// 新增命名空间 自定义
///
/// Demo
/// var codeNamespace = new List<CodeNamespaceImport>()
/// {
/// new CodeNamespaceImport("namespace")
/// };
/// </summary>
/// <param name="codeNamespaceImport"></param>
public CodeMake AddNamespaces(Func<List<CodeNamespaceImport>> codeNamespaceImport)
{
if (BeforeAddNamespace != null)
{
BeforeAddNamespace();
}
codeNamespaceImport().ForEach(c => _samples.Imports.Add(c));
if (AfterAddNamespace != null)
{
AfterAddNamespace();
}
return this;
}
#endregion
#region Inherit Function Area
/// <summary>
/// 继承接口名称
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public CodeMake AddInherit(string name)
{
_targetClass.BaseTypes.Add(name);
return this;
}
/// <summary>
/// 继承接口类型
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public CodeMake AddInherit(Type name)
{
_targetClass.BaseTypes.Add(name);
return this;
}
#endregion
#region Constructor Function Area
/// <summary>
/// 添加构造函数
/// </summary>
/// <param name="ctor">ctor</param>
public CodeMake AddConstructor(ConstructorEntity ctor)
=> AddConstructor(() =>
{
if (ctor is null)
{
throw new ArgumentException("构造函数基本访问类型参数不能为空");
}
// Declare the constructor
CodeConstructor constructor = new CodeConstructor();
constructor.Attributes = ctor.Attr;
if (ctor.Params != null)
{
ctor.Params.ForEach(s =>
{
// Add parameters.
constructor.Parameters.Add(new CodeParameterDeclarationExpression(
s.ParamType, s.Name));
if (!string.IsNullOrEmpty(s.ReferenceName))
{
// Add field initialization logic
CodeFieldReferenceExpression reference =
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), s.ReferenceName);
constructor.Statements.Add(new CodeAssignStatement(reference,
new CodeArgumentReferenceExpression(s.Name)));
}
});
}
return constructor;
});
/// <summary>
/// 添加构造函数
/// </summary>
/// <param name="ctor">ctor</param>
public CodeMake AddConstructor(Func<CodeConstructor> ctor)
{
if (BeforeAddConstructor != null)
{
BeforeAddConstructor();
}
_targetClass.Members.Add(ctor());
if (AfterAddConstructor != null)
{
AfterAddConstructor();
}
return this;
}
#endregion
#region Field Function Area
/// <summary>
/// 新增字段
/// </summary>
/// <param name="FieldEntity">字段Model</param>
public CodeMake AddField(FieldEntity fieldModel)
=> AddField(() =>
{
if (fieldModel is null)
{
throw new ArgumentException("字段参数信息不能为null");
}
return GetFieldBy(fieldModel);
});
/// <summary>
/// 新增多个字段
/// </summary>
/// <param name="FieldEntity">字段Model</param>
public CodeMake AddFields(List<FieldEntity> fields)
{
fields.ForEach(f => AddField(f));
return this;
}
/// <summary>
/// 新增字段
/// </summary>
/// <param name="attr">字段标签</param>
/// <param name="fieldName">字段名称</param>
/// <param name="fieldType">字段类型</param>
/// <param name="comment">字段注释</param>
public CodeMake AddField(string fieldName, Type fieldType, MemberAttributes attr = MemberAttributes.Public , object defaultValue = default, string comment = null)
=> AddField(
new FieldEntity(fieldName, fieldType)
{
Attr = attr,
Comment = comment,
DefaultValue = defaultValue,
});
/// <summary>
/// 新增字段(自定义)
///
/// 示例:
/// CodeMemberField field = new CodeMemberField();
/// field.Attributes = attr;
/// field.Name = fieldName;
/// field.Type = new CodeTypeReference(fieldType);
/// if (!string.IsNullOrEmpty(comment))
/// {
/// field.Comments.Add(new CodeCommentStatement(comment));
/// }
/// return field;
/// </summary>
/// <param name="fieldMember">字段类型</param>
public CodeMake AddField(Func<CodeMemberField> fieldMember)
=> AddFields(() => new List<CodeMemberField> { fieldMember() });
/// <summary>
/// 新增多个字段(自定义)
///
///
/// Demo:
/// List<CodeMemberField> fields = new List<CodeMemberField>();
/// CodeMemberField field = new CodeMemberField();
/// field.Attributes = attr;
/// field.Name = fieldName;
/// field.Type = new CodeTypeReference(fieldType);
/// if (!string.IsNullOrEmpty(comment))
/// {
/// field.Comments.Add(new CodeCommentStatement(comment));
/// }
/// fields.Add(field);
/// return fields;
///
/// </summary>
/// <param name="fieldMember"></param>
public CodeMake AddFields(Func<List<CodeMemberField>> fieldMember)
{
if (BeforeAddField != null)
{
BeforeAddField();
}
fieldMember().ForEach(f => _targetClass.Members.Add(f));
if (AfterAddField != null)
{
AfterAddField();
}
return this;
}
private CodeMemberField GetFieldBy(FieldEntity fieldModel)
{
// Declare the Value field.
CodeMemberField field = new CodeMemberField(new CodeTypeReference(fieldModel.Type), fieldModel.Name);
field.Attributes = fieldModel.Attr;
if (fieldModel.DefaultValue != null)
{
field.InitExpression = new CodePrimitiveExpression(fieldModel.DefaultValue);
}
if (!string.IsNullOrEmpty(fieldModel.Comment))
{
field.Comments.Add(new CodeCommentStatement(fieldModel.Comment));
}
return field;
}
#endregion
#region Properties Function Area
/// <summary>
/// 新增属性
/// </summary>
/// <param name="pro">属性Model</param>
public CodeMake AddPropertie(PropertyEntity pro)
=> AddProperties(() =>
{
if (pro is null)
{
throw new ArgumentException("属性参数信息不能为null");
}
// Declare the read-only Width property.
string fieldName = string.Empty;
if (pro.HasGet && pro.HasSet)
{
fieldName = pro.Name + " { get; set; }//";
}
else if (pro.HasGet && !pro.HasSet)
{
fieldName = pro.Name + " { get; }//";
}
else
{
throw new ArgumentException("属性不能设置只写或当成字段来使用");
}
var propertity = GetFieldBy(new FieldEntity(fieldName, pro.Type)
{
Attr = pro.Attr,
Comment = pro.Comment
});
return new List<CodeTypeMember> { propertity };
});
/// <summary>
/// 增加属性
/// </summary>
/// <param name="attr">属性标签</param>
/// <param name="propertieName">属性名称</param>
/// <param name="propertieType">属性类型</param>
/// <param name="comment">属性注释</param>
public CodeMake AddPropertie(MemberAttributes attr, string propertieName, Type propertieType, string comment = null)
=> AddPropertie(new PropertyEntity(propertieName, propertieType)
{
HasGet = true,
HasSet = true,
Comment = comment
});
/// <summary>
/// 添加多个属性
/// </summary>
/// <param name="pros"></param>
public CodeMake AddProperties(List<PropertyEntity> pros)
{
pros.ForEach(s => AddPropertie(s));
return this;
}
/// <summary>
/// 新增1个属性(自定义)
/// </summary>
/// <param name="propertyMember">Func CodeTypeMember</param>
public CodeMake AddPropertie(Func<CodeTypeMember> propertyMember)
=> AddProperties(() => new List<CodeTypeMember>
{
propertyMember()
}
);
/// <summary>
/// 新增多个属性(自定义)
/// </summary>
/// <param name="propertyMember">Func list CodeTypeMember</param>
public CodeMake AddProperties(Func<List<CodeTypeMember>> propertyMember)
{
if (BeforeAddPropertie != null)
{
BeforeAddPropertie();
}
propertyMember().ForEach(p => _targetClass.Members.Add(p));
if (AfterAddPropertie != null)
{
AfterAddPropertie();
}
return this;
}
#endregion
#region Method Area
/// <summary>
/// 添加方法
/// </summary>
/// <param name="methods">方法</param>
/// <returns>this</returns>
public CodeMake AddMethod(string method, string comment = null)
=> AddMethod(new MethodEntity { Method = method, Comment = comment });
/// <summary>
/// 添加单个方法
/// </summary>
/// <param name="methods">方法</param>
/// <returns>this</returns>
public CodeMake AddMethod(MethodEntity method)
=> AddMethods(new List<MethodEntity> { method });
/// <summary>
/// 添加多个方法
/// </summary>
/// <param name="methods">方法集合</param>
/// <returns>this</returns>
public CodeMake AddMethods(List<MethodEntity> methods)
=> AddMethods(() =>
{
var methodsList = new List<CodeTypeMember>();
methods.ForEach(m =>
{
CodeSnippetTypeMember snippet = new CodeSnippetTypeMember
{
Text = m.Method
};
if (!string.IsNullOrEmpty(m.Comment))
{
snippet.Comments.Add(new CodeCommentStatement(m.Comment, false));
}
methodsList.Add(snippet);
});
return methodsList;
});
/// <summary>
/// 添加方法(自定义)
/// </summary>
/// <param name="method">Func<CodeTypeMember></param>
public CodeMake AddMethod(Func<CodeTypeMember> method)
=> AddMethods(() => new List<CodeTypeMember> { method() });
/// <summary>
/// 添加多个方法(自定义)
/// </summary>
/// <param name="method">Func<List<CodeTypeMember>></param>
public CodeMake AddMethods(Func<List<CodeTypeMember>> method)
{
if (BeforeAddMethod != null)
{
BeforeAddMethod();
}
method().ForEach(m => _targetClass.Members.Add(m));
if (AfterAddMethod != null)
{
AfterAddMethod();
}
return this;
}
#endregion
#region OutPut
/// <summary>
/// 控制台输出
/// </summary>
/// <returns></returns>
public CodeMake Log()
{
Console.WriteLine(GenerateCSharpString());
return this;
}
/// <summary>
/// 元数据引用控制台输出
/// </summary>
/// <returns></returns>
public CodeMake MetadataLog()
{
foreach (var item in _assemblyUsingLocation)
{
Console.WriteLine(item);
}
return this;
}
/// <summary>
/// 文本输出(string)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public string GenerateCSharpString()
=> CodeDomOutString(() =>
{
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions { BracingStyle = "C" };
using (StringWriter sourceWriter = new StringWriter())
{
provider.GenerateCodeFromCompileUnit(_targetUnit, sourceWriter, options);
return sourceWriter.ToString();
}
});
/// <summary>
/// 自定义CodeDom输出(string)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public string CodeDomOutString(Func<string> codeDomContext)
=> codeDomContext();
/// <summary>
/// 文件输出(.cs)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public CodeMake GenerateCSharpFile(string fileFullPath)
{
if (string.IsNullOrEmpty(fileFullPath))
{
throw new ArgumentException("文件输出路径为空,请设置输出路径!");
}
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
using (StreamWriter sourceWriter = new StreamWriter(fileFullPath))
{
provider.GenerateCodeFromCompileUnit(
_targetUnit, sourceWriter, options);
}
return this;
}
/// <summary>
/// 文件输出(.cs)
/// </summary>
public CodeMake CodeDomOutFile()
=> GenerateCSharpFile(_outputFileName);
#endregion
#region CreateInstance Function Area
/// <summary>
/// 创建单例对象 默认获取方式为命名空间+类名
/// </summary>
/// <returns></returns>
public object CreateInstanceOfSingleton()
=> CreateInstanceOfSingleton(this.GenerateCSharpString(), this.FullNameSpaceWithClass);
/// <summary>
/// 创建单例对象 存取Key自定义
/// </summary>
/// <param name="singletonKey"></param>
/// <returns></returns>
public object CreateInstanceOfSingleton(string singletonKey)
=> CreateInstanceOfSingleton(this.GenerateCSharpString(), singletonKey);
/// <summary>
/// 创建单例对象 按命名空间+类名区分
/// </summary>
/// <param name="context">创建对象文本</param>
/// <param name="singletonKey">命名空间+类名称</param>
/// <returns></returns>
public object CreateInstanceOfSingleton(string context, string singletonKey)
{
if (HasSingletonInstance(singletonKey))
{
return GetSingletonInstanceBy(singletonKey);
}
var instance = CreateInstance(context, this.FullNameSpaceWithClass);
_singletonContainer.Add(singletonKey, instance);
return instance;
}
/// <summary>
/// 根据本类构建对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance()
=> CreateInstance(this.GenerateCSharpString(), this.FullNameSpaceWithClass);
/// <summary>
/// 根据传入内容构建对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance(string context, string fullNamespaceClass)
=> CreateInstance(() =>
{
#region Verify
if (string.IsNullOrEmpty(context))
{
throw new ArgumentException("生成的代码不能为空");
}
if (string.IsNullOrEmpty(fullNamespaceClass))
{
throw new ArgumentException("命名空间和类名称不能为空");
}
#endregion
#region 加载构建
//元数据加载
if (_assemblyLoad != null)
{
_assemblyLoad();
}
MetadataReference[] references = _assemblyUsingLocation.ToArray().Select(r => MetadataReference.CreateFromFile(r)).ToArray();
CSharpCompilation compilation = CSharpCompilation.Create(
Path.GetRandomFileName(),
syntaxTrees: new[] { CSharpSyntaxTree.ParseText(context) },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
#endregion
#region 创建对象
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (result.Success)
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
//var type = assembly.GetType("CodeDOM.CodeDOMCreatedClass");
return assembly.CreateInstance(fullNamespaceClass);
}
else
{
return result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
}
}
#endregion
});
/// <summary>
/// 构建自定义生成方式和对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance(Func<object> createInfo)
{
if (BeforeCreateInstance != null)
{
BeforeCreateInstance();
}
var resultObj = createInfo();
if (AfterCreateInstance != null)
{
AfterCreateInstance();
}
return resultObj;
}
#endregion
#region Singleton Ioc Function Area
/// <summary>
/// 获取单例对象
/// </summary>
/// <param name="key">命名空间+类名称</param>
/// <returns></returns>
public static object GetSingletonInstanceBy(string key)
=> HasSingletonInstance(key) ? _singletonContainer[key] : null;
/// <summary>
/// 是否包含单例对象
/// </summary>
/// <param name="key">命名空间+类名称</param>
/// <returns></returns>
public static bool HasSingletonInstance(string key)
=> _singletonContainer.ContainsKey(key);
#endregion
}
CodeMaker
咱们开发,碰到不知道的类一般怎么办,那肯定是先 new一个,再看看参数再说,然后连蒙带猜的写。
所以,我们说一些私有字段 然后讲构造函数。
使用起来大多数人都是
CodeMacker code = new CodeMacker();
传参数,传啥参数,我哪儿知道。
private CodeNamespace _samples;
private CodeCompileUnit _targetUnit;
private CodeTypeDeclaration _targetClass;
private readonly string _outputFileName;
/// <summary>
/// 命名空间
/// </summary>
public string NameSpace { get; private set; }
/// <summary>
/// 类名称
/// </summary>
public string ClassName { get; private set; }
/// <summary>
/// 命名空间+类名称
/// </summary>
public string FullNameSpaceWithClass { get; private set; }
这几个是基本需要的参数,干嘛的就看名称猜吧,具体实现讲起来太累,看官网文档好点。
如果看了上面源码的就会发现少了点东西,没有了 一个字典和一堆Event,那个等会再说。
然后我们看构造函数
#region Ctor
public CodeMacker(Action<CodeMacker> eventCallBack = null)
: this("CodeDOM", eventCallBack)
{
}
public CodeMacker(string nameSpace,Action<CodeMacker> eventCallBack = null)
: this(nameSpace, "System", eventCallBack)
{
}
public CodeMacker(string nameSpace, string usingNameSpace, Action<CodeMacker> eventCallBack = null)
: this(nameSpace, usingNameSpace, "CreatedClass", eventCallBack)
{
}
public CodeMacker(string nameSpace, string usingNameSpace, string className, Action<CodeMacker> eventCallBack = null)
: this(nameSpace, usingNameSpace, className, TypeAttributes.Public, eventCallBack)
{
}
public CodeMacker(string nameSpace, string usingNameSpace, string className, TypeAttributes visitAttr, Action<CodeMacker> eventCallBack = null)
: this(nameSpace, usingNameSpace, className, visitAttr, "C:\\", eventCallBack)
{
}
public CodeMacker(string nameSpace, string usingNameSpace, string className, TypeAttributes visitAttr, string fileFullPath, Action<CodeMacker> eventCallBack = null)
{
#region Verify Area
if (string.IsNullOrEmpty(nameSpace))
{
throw new ArgumentException("命名空间不能为空");
}
if (string.IsNullOrEmpty(className))
{
throw new ArgumentException("类名不能为空");
}
#endregion
if (eventCallBack != null)
{
eventCallBack(this);
}
if (_onecEventNotRun)
{
if (DoOnceWorkBeforeConstructor != null)
{
DoOnceWorkBeforeConstructor();
_onecEventNotRun = false;
}
}
if (BeforeConstructor != null)
{
BeforeConstructor();
}
#region Main
_targetUnit = new CodeCompileUnit();
_samples = new CodeNamespace(nameSpace);
_samples.Imports.Add(new CodeNamespaceImport(usingNameSpace));
_targetClass = new CodeTypeDeclaration(className);
_targetClass.IsClass = true;
_targetClass.TypeAttributes = visitAttr;
_samples.Types.Add(_targetClass);
_targetUnit.Namespaces.Add(_samples);
NameSpace = nameSpace;
ClassName = className;
FullNameSpaceWithClass = NameSpace + "." + ClassName;
_outputFileName = fileFullPath;
#endregion
if (AfterConstructor != null)
{
AfterConstructor();
}
}
#endregion
其实写了半天主要就是最后一个,剩下的我都自动默认了。
默认构造函数可空,那里留了个Action,那是用来做扩展的,咱们最后再说,不过如果你踏踏实实的看下来了,应该也猜个差不多了。
剩下的就是初始化一些内容,如果你不填你创建的这个对象类名,命名空间啥的,我就随便给你写一份。反正你也不关心
你只需要记住,在你new的时候,我会先触发一次且仅一次的callback给你做扩展,至于扩展啥,我也不知道。
然后开始了构建构造函数和基本的对象实例等等啥的。
在这里有2个时间点可以扩展,分别是构造前和构造后,2个callback
然后没啥好说的了
==========================================白活线====================================================
下面看怎么加命名空间
#region NameSpaceAdded Function Area
/// <summary>
/// 新增命名空间
/// </summary>
/// <param name="codeNamespaceImport">命名空间文本,不需要添加using</param>
public CodeMacker AddNamespace(string codeNamespaceImport)
=> AddNamespaces(() => new List<CodeNamespaceImport> { new CodeNamespaceImport(codeNamespaceImport) });
/// <summary>
/// 新增多个命名空间
/// </summary>
/// <param name="codeNamespaceImport">命名空间文本,不需要添加using</param>
public CodeMacker AddNamespaces(List<string> codeNamespaceImport)
{
List<CodeNamespaceImport> codeNamespace = new List<CodeNamespaceImport>();
codeNamespaceImport.ForEach(c => codeNamespace.Add(new CodeNamespaceImport(c)));
return AddNamespaces(() => codeNamespace);
}
/// <summary>
/// 新增命名空间 自定义
///
/// Demo
/// var codeNamespace = new CodeNamespaceImport>("namespace");
/// </summary>
/// <param name="codeNamespaceImport"></param>
public CodeMacker AddNamespace(Func<CodeNamespaceImport> codeNamespaceImport)
=> AddNamespaces(() => new List<CodeNamespaceImport> { codeNamespaceImport() });
/// <summary>
/// 新增命名空间 自定义
///
/// Demo
/// var codeNamespace = new List<CodeNamespaceImport>()
/// {
/// new CodeNamespaceImport("namespace")
/// };
/// </summary>
/// <param name="codeNamespaceImport"></param>
public CodeMacker AddNamespaces(Func<List<CodeNamespaceImport>> codeNamespaceImport)
{
if (BeforeAddNamespace != null)
{
BeforeAddNamespace();
}
codeNamespaceImport().ForEach(c => _samples.Imports.Add(c));
if (AfterAddNamespace != null)
{
AfterAddNamespace();
}
return this;
}
#endregion
这里,就是你引用包的一些地方,比如你这个类要引用一些个命名空间,就这玩意儿,用的时候不用加using
调用很简单,就是直接传字符串,多的话扔个List
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
然后是构造函数,这里的构造函数是指的构造你这个生成对象的构造函数,不是构造这个类的方法
#region Constructor Function Area
/// <summary>
/// 添加构造函数
/// </summary>
/// <param name="ctor">ctor</param>
public CodeMacker AddConstructor(ConstructorEntity ctor)
=> AddConstructor(
() =>
{
if (ctor is null)
{
throw new ArgumentException("构造函数基本访问类型参数不能为空");
}
// Declare the constructor
CodeConstructor constructor = new CodeConstructor();
constructor.Attributes = ctor.Attr;
if (ctor.Params != null)
{
ctor.Params.ForEach(s =>
{
// Add parameters.
constructor.Parameters.Add(new CodeParameterDeclarationExpression(
s.ParamType, s.Name));
if (!string.IsNullOrEmpty(s.ReferenceName))
{
// Add field initialization logic
CodeFieldReferenceExpression reference =
new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), s.ReferenceName);
constructor.Statements.Add(new CodeAssignStatement(reference,
new CodeArgumentReferenceExpression(s.Name)));
}
});
}
return constructor;
});
/// <summary>
/// 添加构造函数
/// </summary>
/// <param name="ctor">ctor</param>
public CodeMacker AddConstructor(Func<CodeConstructor> ctor)
{
if (BeforeAddConstructor != null)
{
BeforeAddConstructor();
}
_targetClass.Members.Add(ctor());
if (AfterAddConstructor != null)
{
AfterAddConstructor();
}
return this;
}
#endregion
怎么传参,New就可以了。比如你的构造函数要public A(int a,intb){}
那就看上一篇里面那个Entity的定义就好,吧参数对应写进去,参数名称,参数类型,给哪个参数赋值。
如果你构造函数不用默认参数,那写这个干啥,默认就是隐藏无参构造函数的。
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
然后是字段了
#region Field Function Area
/// <summary>
/// 新增字段
/// </summary>
/// <param name="FieldEntity">字段Model</param>
public CodeMacker AddField(FieldEntity fieldModel)
=> AddField(() =>
{
if (fieldModel is null)
{
throw new ArgumentException("字段参数信息不能为null");
}
return GetFieldBy(fieldModel);
});
/// <summary>
/// 新增多个字段
/// </summary>
/// <param name="FieldEntity">字段Model</param>
public CodeMacker AddFields(List<FieldEntity> fields)
{
fields.ForEach(f => AddField(f));
return this;
}
/// <summary>
/// 新增字段
/// </summary>
/// <param name="attr">字段标签</param>
/// <param name="fieldName">字段名称</param>
/// <param name="fieldType">字段类型</param>
/// <param name="comment">字段注释</param>
public CodeMacker AddField(MemberAttributes attr, string fieldName, Type fieldType, object defaultValue = default, string comment = null)
=> AddField(
new FieldEntity(fieldName, fieldType)
{
Attr = attr,
Comment = comment,
DefaultValue = defaultValue,
});
/// <summary>
/// 新增字段(自定义)
///
/// 示例:
/// CodeMemberField field = new CodeMemberField();
/// field.Attributes = attr;
/// field.Name = fieldName;
/// field.Type = new CodeTypeReference(fieldType);
/// if (!string.IsNullOrEmpty(comment))
/// {
/// field.Comments.Add(new CodeCommentStatement(comment));
/// }
/// return field;
/// </summary>
/// <param name="fieldMember">字段类型</param>
public CodeMacker AddField(Func<CodeMemberField> fieldMember)
=> AddFields(() => new List<CodeMemberField> { fieldMember() });
/// <summary>
/// 新增多个字段(自定义)
///
///
/// Demo:
/// List<CodeMemberField> fields = new List<CodeMemberField>();
/// CodeMemberField field = new CodeMemberField();
/// field.Attributes = attr;
/// field.Name = fieldName;
/// field.Type = new CodeTypeReference(fieldType);
/// if (!string.IsNullOrEmpty(comment))
/// {
/// field.Comments.Add(new CodeCommentStatement(comment));
/// }
/// fields.Add(field);
/// return fields;
///
/// </summary>
/// <param name="fieldMember"></param>
public CodeMacker AddFields(Func<List<CodeMemberField>> fieldMember)
{
if (BeforeAddField != null)
{
BeforeAddField();
}
fieldMember().ForEach(f => _targetClass.Members.Add(f));
if (AfterAddField != null)
{
AfterAddField();
}
return this;
}
private CodeMemberField GetFieldBy(FieldEntity fieldModel)
{
// Declare the Value field.
CodeMemberField field = new CodeMemberField(new CodeTypeReference(fieldModel.Type), fieldModel.Name);
field.Attributes = fieldModel.Attr;
if (fieldModel.DefaultValue != null)
{
field.InitExpression = new CodePrimitiveExpression(fieldModel.DefaultValue);
}
if (!string.IsNullOrEmpty(fieldModel.Comment))
{
field.Comments.Add(new CodeCommentStatement(fieldModel.Comment));
}
return field;
}
#endregion
字段就是把对象New进去,或者直接写参数,有留出来的一个方法,其实底下我也是自己new了一个,没啥区别,看使用习惯。
new的时候强制你要写名称和类型,都定好了,不写不行你,这个也没啥好说的,比较简单
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
然后是属性了,属性稍微有点东西讲一点
#region Properties Function Area
/// <summary>
/// 新增属性
/// </summary>
/// <param name="pro">属性Model</param>
public CodeMacker AddPropertie(PropertyEntity pro)
=> AddProperties(() =>
{
if (pro is null)
{
throw new ArgumentException("属性参数信息不能为null");
}
// Declare the read-only Width property.
string fieldName = string.Empty;
if (pro.HasGet && pro.HasSet)
{
fieldName = pro.Name + " { get; set; }//";
}
else if (pro.HasGet && !pro.HasSet)
{
fieldName = pro.Name + " { get; }//";
}
else
{
throw new ArgumentException("属性不能设置只写或当成字段来使用");
}
var propertity = GetFieldBy(new FieldEntity(fieldName, pro.Type)
{
Attr = pro.Attr,
Comment = pro.Comment
});
return new List<CodeTypeMember> { propertity };
});
/// <summary>
/// 增加属性
/// </summary>
/// <param name="attr">属性标签</param>
/// <param name="propertieName">属性名称</param>
/// <param name="propertieType">属性类型</param>
/// <param name="comment">属性注释</param>
public CodeMacker AddPropertie(MemberAttributes attr, string propertieName, Type propertieType, string comment = null)
=> AddPropertie(new PropertyEntity(propertieName, propertieType)
{
HasGet = true,
HasSet = true,
Comment = comment
});
/// <summary>
/// 添加多个属性
/// </summary>
/// <param name="pros"></param>
public CodeMacker AddProperties(List<PropertyEntity> pros)
{
pros.ForEach(s => AddPropertie(s));
return this;
}
/// <summary>
/// 新增1个属性(自定义)
/// </summary>
/// <param name="propertyMember">Func CodeTypeMember</param>
public CodeMacker AddPropertie(Func<CodeTypeMember> propertyMember)
=> AddProperties(() => new List<CodeTypeMember>
{
propertyMember()
}
);
/// <summary>
/// 新增多个属性(自定义)
/// </summary>
/// <param name="propertyMember">Func list CodeTypeMember</param>
public CodeMacker AddProperties(Func<List<CodeTypeMember>> propertyMember)
{
if (BeforeAddPropertie != null)
{
BeforeAddPropertie();
}
propertyMember().ForEach(p => _targetClass.Members.Add(p));
if (AfterAddPropertie != null)
{
AfterAddPropertie();
}
return this;
}
#endregion
如果你,如果哈,如果你认真的看了方法,你就会发现,我特|么的不是还是字段吗,没错。就是这样
官方给的默认方法是这样的,如果是生成的属性,没有自动属性,必须得在get和set里写逻辑,但是说白了大多时候我们不需要这么做(懒)
所以就写个自动属性,但是问题在于官方没有给自动属性的操作方式。
在第一章里我说过,CodeDom本身是生成个字符串,所以费那脑子干嘛,
字段加点料,不就行了?(我才不会说我也是查到的,啊哈哈哈哈)
其他没有区别了,加多个,单个都可以。如果你有写get,set逻辑的需求,那就去调用func自己写。
但是需要你自己去学习CodeDom那些弯弯道道了,我反正是懒得写了。
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
这里该说方法了,方法,很重要的一环。但是,异常简单。甚至没什么好说的。
#region Method Area
/// <summary>
/// 添加方法
/// </summary>
/// <param name="methods">方法</param>
/// <returns>this</returns>
public CodeMacker AddMethod(string method, string comment = null)
=> AddMethod(new MethodEntity { Method = method, Comment = comment });
/// <summary>
/// 添加单个方法
/// </summary>
/// <param name="methods">方法</param>
/// <returns>this</returns>
public CodeMacker AddMethod(MethodEntity method)
=> AddMethods(new List<MethodEntity> { method });
/// <summary>
/// 添加多个方法
/// </summary>
/// <param name="methods">方法集合</param>
/// <returns>this</returns>
public CodeMacker AddMethods(List<MethodEntity> methods)
=> AddMethods(() =>
{
var methodsList = new List<CodeTypeMember>();
methods.ForEach(m =>
{
CodeSnippetTypeMember snippet = new CodeSnippetTypeMember
{
Text = m.Method
};
if (!string.IsNullOrEmpty(m.Comment))
{
snippet.Comments.Add(new CodeCommentStatement(m.Comment, false));
}
methodsList.Add(snippet);
});
return methodsList;
});
/// <summary>
/// 添加方法(自定义)
/// </summary>
/// <param name="method">Func<CodeTypeMember></param>
public CodeMacker AddMethod(Func<CodeTypeMember> method)
=> AddMethods(() => new List<CodeTypeMember> { method() });
/// <summary>
/// 添加多个方法(自定义)
/// </summary>
/// <param name="method">Func<List<CodeTypeMember>></param>
public CodeMacker AddMethods(Func<List<CodeTypeMember>> method)
{
if (BeforeAddMethod != null)
{
BeforeAddMethod();
}
method().ForEach(m => _targetClass.Members.Add(m));
if (AfterAddMethod != null)
{
AfterAddMethod();
}
return this;
}
#endregion
其实看了这么多,你会发现,我写的代码都差不多,圈套圈的。实现就那一个。
本来方法是很复杂的一个内容,里面可能要写for,if,while,event,action ,obj…..
官方给的逻辑非常之复杂
复杂到我不想学了,但是,但是,但是我找到了一个非常简单的方法,那就是,你给我把方法传个字符串进来,我给你生成。
没错,就是字面意思。传个字符串。具体怎么用,后面有示例。
如果你有自定义生成的需求,那就调用Fun
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
ok。到此为止,基本上都有了,命名空间,类,字段,属性,方法都齐活儿了。
那就应该是输出了对吧,。
来,我们看输出。
#region OutPut
/// <summary>
/// 控制台输出
/// </summary>
/// <returns></returns>
public CodeMacker Log()
{
CodeDomProvider prvd = CodeDomProvider.CreateProvider("cs");
prvd.GenerateCodeFromCompileUnit(_targetUnit, Console.Out, null);
return this;
}
/// <summary>
/// 文本输出(string)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public string GenerateCSharpString()
=> CodeDomOutString(() =>
{
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions { BracingStyle = "C" };
using (StringWriter sourceWriter = new StringWriter())
{
provider.GenerateCodeFromCompileUnit(_targetUnit, sourceWriter, options);
return sourceWriter.ToString();
}
});
/// <summary>
/// 自定义CodeDom输出(string)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public string CodeDomOutString(Func<string> codeDomContext)
=> codeDomContext();
/// <summary>
/// 文件输出(.cs)
/// </summary>
/// <param name="fileFullPath">文件地址</param>
public CodeMacker GenerateCSharpFile(string fileFullPath)
{
if (string.IsNullOrEmpty(fileFullPath))
{
throw new ArgumentException("文件输出路径为空,请设置输出路径!");
}
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
using (StreamWriter sourceWriter = new StreamWriter(fileFullPath))
{
provider.GenerateCodeFromCompileUnit(
_targetUnit, sourceWriter, options);
}
return this;
}
/// <summary>
/// 文件输出(.cs)
/// </summary>
public CodeMacker CodeDomOutFile()
=> GenerateCSharpFile(_outputFileName);
#endregion
第一个是控制台输出,调试的时候用这个,能直接看到生成的对象类。
第二个是文本输出,也就是我们的核心方法,生成对象全靠它
第三个是自定义输出,你自己爱怎么玩怎么玩。
第四个是文件输出,如果你碰到生成对象后怎么调用也无法成功的时候,记住,输出个文本,你会找到问题的。v1=🤞😁😁😁
最后一个略过
怎么用就不说了,这里没有时间节点扩展,别找了。
写Fun
==========================================白活线====================================================
重头戏来了,怎么生成对象呢,就在这里
看代码先
#region CreateInstance Function Area
/// <summary>
/// 创建单例对象 按命名空间+类名区分
/// </summary>
/// <returns></returns>
public object CreateInstanceOfSingleton()
=> CreateInstanceOfSingleton(this.GenerateCSharpString(), this.FullNameSpaceWithClass);
/// <summary>
/// 创建单例对象 按命名空间+类名区分
/// </summary>
/// <param name="context">创建对象文本</param>
/// <param name="fullNamespaceClass">命名空间+类名称</param>
/// <returns></returns>
public object CreateInstanceOfSingleton(string context, string fullNamespaceClass)
{
if (HasSingletonInstance(fullNamespaceClass))
{
return GetSingletonInstanceBy(fullNamespaceClass);
}
var instance = CreateInstance(context, fullNamespaceClass);
_singletonContainer.Add(fullNamespaceClass, instance);
return instance;
}
/// <summary>
/// 根据本类构建对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance()
=> CreateInstance(this.GenerateCSharpString(), this.FullNameSpaceWithClass);
/// <summary>
/// 根据传入内容构建对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance(string context, string fullNamespaceClass)
=> CreateInstance(() =>
{
#region Verify
if (string.IsNullOrEmpty(context))
{
throw new ArgumentException("生成的代码不能为空");
}
if (string.IsNullOrEmpty(fullNamespaceClass))
{
throw new ArgumentException("命名空间和类名称不能为空");
}
#endregion
#region 加载构建
var refPaths = new[]
{
typeof(System.Object).GetTypeInfo().Assembly.Location,
typeof(Console).GetTypeInfo().Assembly.Location,
Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), "System.Runtime.dll")
};
MetadataReference[] references = refPaths.Select(r => MetadataReference.CreateFromFile(r)).ToArray();
CSharpCompilation compilation = CSharpCompilation.Create(
Path.GetRandomFileName(),
syntaxTrees: new[] { CSharpSyntaxTree.ParseText(context) },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
#endregion
#region 创建对象
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (result.Success)
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
//var type = assembly.GetType("CodeDOM.CodeDOMCreatedClass");
return assembly.CreateInstance(fullNamespaceClass);
}
else
{
return result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
}
}
#endregion
});
/// <summary>
/// 构建自定义生成方式和对象
/// </summary>
/// <returns>返回Object类,根据内容反射获取信息</returns>
public object CreateInstance(Func<object> createInfo)
{
if (BeforeCreateInstance != null)
{
BeforeCreateInstance();
}
var resultObj = createInfo();
if (AfterCreateInstance != null)
{
AfterCreateInstance();
}
return resultObj;
}
#endregion
#region Singleton Ioc Function Area
/// <summary>
/// 获取单例对象
/// </summary>
/// <param name="key">命名空间+类名称</param>
/// <returns></returns>
public static object GetSingletonInstanceBy(string key)
=> HasSingletonInstance(key) ? _singletonContainer[key] : null;
/// <summary>
/// 是否包含单例对象
/// </summary>
/// <param name="key">命名空间+类名称</param>
/// <returns></returns>
public static bool HasSingletonInstance(string key)
=> _singletonContainer.ContainsKey(key);
#endregion
这里我做了两套,一套是单例,一套是瞬时(普通new)至于为什么没有Scope,因为我没有Scope的作用域呀,啊哈哈哈哈啊
单例的方法是在最上面,有一个字典
/// <summary>
/// 单例IOC容器
/// </summary>
private static Dictionary<string, object> _singletonContainer = new Dictionary<string, object>();
从这里存取。
重点说生成实例方法。
CodeDom在FrameWork的时代里面是支持直接生成对象的,但是如果在NetCore或者Net5当中是不支持直接生成,会报平台错误,具体怎么我就不演示了
没有意义,如果你是FrameWork使用的话,可以找一找代码,那个很简单,几行。
我这里是用了Emit来进行操作,怎么个逻辑调用跑来跑去的就那一堆,我看了半天也懒得分析了,直接用吧,还挺好。性能,算了,这里我们不说性能,如果有好的意见也可以提出来,我看心情改,啊哈哈哈哈哈
这里就是把字符串传进去,然后生成对象,就这样。多余的内容我封装好了。
单例默认用命名空间+类来作为Key,你自定义也可以,传给我
怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback
写Fun
==========================================白活线====================================================
最后我们来看一下所有的时间节点。
#region CodeMaker Filter 节点
private static bool _onecEventNotRun = true;
/// <summary>
/// 整个项目运行中只调用一次的事件,事件发生点在尚未构造对象之前
/// </summary>
public event Action DoOnceWorkBeforeConstructor = null;
/// <summary>
/// 开始构造函数之前
/// </summary>
public event Action BeforeConstructor = null;
/// <summary>
/// 结束构造函数时
/// </summary>
public event Action AfterConstructor = null;
/// <summary>
/// 添加命名空间之前(生成代码 AddNamespace)
/// </summary>
public event Action BeforeAddNamespace = null;
/// <summary>
/// 添加命名空间之后(生成代码 AddNamespace)
/// </summary>
public event Action AfterAddNamespace = null;
/// <summary>
/// 添加构造函数之前(生成代码 AddConstructor)
/// </summary>
public event Action BeforeAddConstructor = null;
/// <summary>
/// 添加构造函数之后(生成代码 AddConstructor)
/// </summary>
public event Action AfterAddConstructor = null;
/// <summary>
/// 添加字段之前(生成代码 AddField)
/// </summary>
public event Action BeforeAddField = null;
/// <summary>
/// 添加字段之后(生成代码 AddField)
/// </summary>
public event Action AfterAddField = null;
/// <summary>
/// 添加属性之前(生成代码 AddPropertie)
/// </summary>
public event Action BeforeAddPropertie = null;
/// <summary>
/// 添加属性之后(生成代码 AddPropertie)
/// </summary>
public event Action AfterAddPropertie = null;
/// <summary>
/// 添加方法之前(生成代码 AddMethod)
/// </summary>
public event Action BeforeAddMethod = null;
/// <summary>
/// 添加方法之后(生成代码 AddMethod)
/// </summary>
public event Action AfterAddMethod = null;
/// <summary>
/// 创建对象之前(生成实例 CreateInstance)
/// </summary>
public event Action BeforeCreateInstance = null;
/// <summary>
/// 创建对象之后(生成实例 CreateInstance)
/// </summary>
public event Action AfterCreateInstance = null;
#endregion
嗯,没什么好说的,在构造函数里初始化赋值就可以了。
好了,你们期待的Demo示例这里我不打算写了,因为我写累了。下一章里写,具体名字叫啥呢,就是CodeDom的完结吧,啊哈哈哈哈哈(恶习多多)
————————————————
原文链接:https://www.cnblogs.com/SevenWang/p/15568399.html