• C#后端之CodeDom在内存中创建对象最简明的讲解(下)附源码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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

     ==========================================白活线====================================================

     然后是构造函数,这里的构造函数是指的构造你这个生成对象的构造函数,不是构造这个类的方法

    #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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    然后是字段了

    #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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    然后是属性了,属性稍微有点东西讲一点

    #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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    这里该说方法了,方法,很重要的一环。但是,异常简单。甚至没什么好说的。

    #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<T>的方法吧,自定义就可以。但是很麻烦。

    怎么用就不说了,这里也有2个时间点可以扩展,分别是开始前和增加后,2个callback

    写Fun<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    重头戏来了,怎么生成对象呢,就在这里

    看代码先

            #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<T>的是留出来的扩展,如果你本身很了解CodeDom可以直接自己写内容使用。

      ==========================================白活线====================================================

    最后我们来看一下所有的时间节点。

         #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的完结吧,啊哈哈哈哈哈(恶习多多)

  • 相关阅读:
    CSS魔法堂:重拾Border之——更广阔的遐想
    CSS魔法堂:重拾Border之——不仅仅是圆角
    CSS魔法堂:重拾Border之——图片作边框
    CSS魔法堂:重拾Border之——解构Border
    CSS3魔法堂:说说Multi-column Layout
    CSS魔法堂:"那不是bug,是你不懂我!" by inline-block
    CSS魔法堂:小结一下Box Model与Positioning Scheme
    CSS魔法堂:说说Float那个被埋没的志向
    CSS魔法堂:你一定误解过的Normal flow
    CSS魔法堂:Absolute Positioning就这个样
  • 原文地址:https://www.cnblogs.com/SevenWang/p/15568399.html
Copyright © 2020-2023  润新知