zoukankan      html  css  js  c++  java
  • 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的完结吧,啊哈哈哈哈哈(恶习多多)

  • 相关阅读:
    Delphi公用函数单元
    Delphi XE5 for Android (十一)
    Delphi XE5 for Android (十)
    Delphi XE5 for Android (九)
    Delphi XE5 for Android (八)
    Delphi XE5 for Android (七)
    Delphi XE5 for Android (五)
    Delphi XE5 for Android (四)
    Delphi XE5 for Android (三)
    Delphi XE5 for Android (二)
  • 原文地址:https://www.cnblogs.com/SevenWang/p/15568399.html
Copyright © 2011-2022 走看看