Autofac 基本使用

发布时间 2023-08-25 15:58:24作者: o李一波o

背景:.Net6.0 常规依赖注入需要不断修改Program.cs文件

需求:实现Repository、IRepository、Razor动态生成并依赖注入(AutoBuildHelper先记录未优化)

引入Autofac、Autofac.Extensions.DependencyInjection
Program.cs添加以下代码:
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer<ContainerBuilder>(builder =>
{
    builder.RegisterModule(new AutoFacManager());
});
实现AutoManager,按你定义的命名规则实现
public class AutoFacManager:Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        var IRepository = Assembly.Load("JK.TitanData.IRepository");
        var Repository = Assembly.Load("JK.TitanData.Repository");
        builder.RegisterAssemblyTypes(IRepository).Where(t => t.Name.EndsWith("IRepository")).AsImplementedInterfaces();
        builder.RegisterAssemblyTypes(Repository).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces();
    }
}

实现AutoBuildHelper
using Newtonsoft.Json;
using SqlSugar;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace JK.TitanData.Util
{
    public class AutoBuildHelper
    {
        private static Razor_Table_PropertyViewModel InitRazor_Table_PropertyViewModel(Razor_Table_Property property)
        {
            Razor_Table_PropertyViewModel table_PropertyViewModel = new Razor_Table_PropertyViewModel();

            table_PropertyViewModel.DoubleClickToEdit = property.DoubleClickToEdit ? "true" : "false";
            table_PropertyViewModel.ShowSearch = property.ShowSearch ? "true" : "false";

            table_PropertyViewModel.ShowDeleteButton = property.ShowDeleteButton ? "true" : "false";
            table_PropertyViewModel.ShowExtendDeleteButton = property.ShowExtendDeleteButton ? "true" : "false";

            table_PropertyViewModel.ShowEditButton = property.ShowEditButton ? "true" : "false";
            table_PropertyViewModel.ShowExtendEditButton = property.ShowExtendEditButton ? "true" : "false";

            table_PropertyViewModel.ShowAddButton = property.ShowAddButton ? "true" : "false";

            return table_PropertyViewModel;
        }
        public static void BuildRazor(Razor razor)
        {
            try
            {
                var filePath = $@"{Path.GetFullPath("../..")}\JK.TitanData\JK.TitanData.Server\Pages\Report\Components\123.razor";
                var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

                var sw = new StreamWriter(fs);
                var propertyViewModel = InitRazor_Table_PropertyViewModel(razor.Table_Property);

                var searchTxt = "";
                var tableColumns = "";
                var assembly = Assembly.LoadFrom(@"D:\Work\Project\JK.TitanData\JK.TitanData.Entity\bin\Debug\net6.0\JK.TitanData.Entity.dll");
                var type = assembly.GetType($"JK.TitanData.Entity.{razor.ClassName}");
                var instance = Activator.CreateInstance(type);
                if (instance != null)
                {
                    var properties = instance.GetType().GetProperties();
                    tableColumns += $@"<TableColumn Width = ""100"" Searchable=""false"" IsReadonlyWhenAdd=true IsReadonlyWhenEdit=true @bind-Field=""@context.Id"" />";
                    for (int i = 0; i < properties.Length; i++)
                    {
                        var property = properties[i];
                        tableColumns += $@"<TableColumn Width = ""100"" Searchable=""true"" IsReadonlyWhenAdd=true IsReadonlyWhenEdit=true @bind-Field=""@context.{property.Name}"" />";
                        tableColumns += "\r\n";

                        if (i == 0)
                            searchTxt += $@"(i.{property.Name}.ToString()?.ToLower() ?? """").Contains(txt)";
                        else
                            searchTxt += $@"|| (i.{property.Name}?.ToString()?.ToLower() ?? """").Contains(txt)";
                        searchTxt += "\r\n";
                    }
                    tableColumns = tableColumns.Substring(0, tableColumns.Length - 2);
                    searchTxt = searchTxt.Substring(0, searchTxt.Length - 2);

                    tableColumns += $@"<TableColumn Width = ""100"" Searchable=""false"" IsReadonlyWhenAdd=false IsReadonlyWhenEdit=true Editable=false @bind-Field=""@context.CreateDate"" />";
                    tableColumns += "\r\n";

                    tableColumns += $@"<TableColumn Width = ""100"" Searchable=""false"" IsReadonlyWhenAdd=false IsReadonlyWhenEdit=true Editable=false @bind-Field=""@context.Creater"" />";
                    tableColumns += "\r\n";

                    tableColumns += $@"<TableColumn Width = ""100"" Searchable=""false"" IsReadonlyWhenAdd=false IsReadonlyWhenEdit=true Editable=false @bind-Field=""@context.Updater"" />";
                    tableColumns += "\r\n";

                    tableColumns += $@"<TableColumn Width = ""100"" Searchable=""false"" IsReadonlyWhenAdd=false IsReadonlyWhenEdit=true Editable=false @bind-Field=""@context.UpdateDate"" />";
                    tableColumns += "\r\n";
                }

                var tableToolbarPopconfirmButtons = "";
                var tableToolbarPopconfirmFunction = "";
                foreach (var item in razor.Table_Toolbars)
                {
                    var color = string.IsNullOrEmpty(item.BtnColor) ? "Color.Secondary" : item.BtnColor;
                    tableToolbarPopconfirmButtons += $@"<TableToolbarPopconfirmButton TItem = ""{razor.ClassName}""
                                          Color=""{color}""
                                          Icon=""fa-fw fa-solid fa-pen-to-square""
                                          IsAsync=""true""
                                          Text=""{item.BtnName}""
                                          OnConfirmCallback=""{item.ProcName}"" />";
                    tableToolbarPopconfirmButtons += "\r\n";

                    if (item.ProcParameters != null && item.ProcParameters.Any() && item.ProcParameters.Count > 1)
                    {
                        var paramters = "";
                        var parameters = new List<SugarParameter>();
                        foreach (KeyValuePair<string, string> keyValue in item.ProcParameters)
                        {
                            parameters.Add(new SugarParameter(keyValue.Key, keyValue.Value));
                        }
                        var parametersStr = JsonConvert.SerializeObject(paramters);
                        var parametersStr2 = JsonConvert.DeserializeObject<List<SugarParameter>>(parametersStr);

                        tableToolbarPopconfirmFunction += $@"
                        async Task<bool> {item.ProcName}(IEnumerable<{razor.ClassName}> items)
                        {{
                            var parametersStr = ""{parametersStr}"";
                            var parameters = JsonConvert.DeserializeObject<List<SugarParameter>>(parametersStr);
                            var result = await Repository.{item.ProcName}(""{item.ProcName}"",parameters);
                            if (result > 0)
                            {{
                                toastService?.Success(""更新成功"");
                            }}
                            else
                            {{
                                toastService?.Error(""更新失败"");
                            }}
                            return result == 0 ? false : true;
                        }}";
                    }
                    else
                    {
                        tableToolbarPopconfirmFunction += $@"
                        async Task<bool> {item.ProcName}(IEnumerable<{razor.ClassName}> items)
                        {{
                            var result = await Repository.{item.ProcName}(""{item.ProcName}"");
                            if (result > 0)
                            {{
                                toastService?.Success(""更新成功"");
                            }}
                            else
                            {{
                                toastService?.Error(""更新失败"");
                            }}
                            return result == 0 ? false : true;
                        }}";
                    }
                    tableToolbarPopconfirmFunction += "\r\n";
                }
                tableToolbarPopconfirmButtons = tableToolbarPopconfirmButtons.Substring(0, tableToolbarPopconfirmButtons.Length - 2);
                tableToolbarPopconfirmFunction = tableToolbarPopconfirmFunction.Substring(0, tableToolbarPopconfirmFunction.Length - 2);

                sw.WriteLine($@"
@page ""{razor.PagePath}""
<Row style = ""padding-top:20px"" ItemsPerRow = ""ItemsPerRow.One"" >
    <Table @ref = ""Table"" TItem = ""{razor.ClassName}""
           PageItemsSource = ""@PageItemsSource""
           @bind - SelectedRows = ""SelectedItems""
           OnDeleteAsync = ""@OnDeleteAsync""
           OnSaveAsync = ""@OnSaveAsync""
           OnQueryAsync = ""@OnQueryAsync""
           OnExportAsync = ""OnExportAsync""
           DoubleClickToEdit = ""{propertyViewModel.DoubleClickToEdit}""
           IsPagination = ""true""
           IsStriped = ""true""
           IsBordered = ""true""
           IsMultipleSelect = ""true""
           IsExtendButtonsInRowHeader = ""true""
           IsFixedHeader = ""true""
           AllowResizing = ""true""
           ShowLoading = ""true""
           ShowToolbar = ""true""
           ShowExtendButtons = ""true""
           ShowExportButton = ""true""
           ShowSearch = ""{propertyViewModel.ShowSearch}""
           ShowColumnList = ""true""
           ShowCardView = ""true""
           ShowDefaultButtons = ""true""
           ShowExtendDeleteButton = ""{propertyViewModel.ShowExtendDeleteButton}""
           ShowDeleteButton = ""{propertyViewModel.ShowDeleteButton}""
           ShowEditButton = ""{propertyViewModel.ShowEditButton}""
           ShowExtendEditButton = ""{propertyViewModel.ShowExtendEditButton}""
           ShowAddButton = ""{propertyViewModel.ShowAddButton}""
           ShowAdvancedSearch = ""true""
           SearchModel = ""@SearchModel""
           SearchMode = ""SearchMode.Popup""
           ShowResetButton = ""true""
           EditMode = ""EditMode.Popup""
           InsertRowMode = ""InsertMode""
           Height = ""@Height""
           class=""table-fix-column-demo""
           RenderMode=""TableRenderMode.Table"">
        <TableColumns>
            {tableColumns}
        </TableColumns>
           <TableToolbarTemplate>
               <a href = ""/Template/{razor.PageName}.xlsx"" target=""_blank"">模板下载</a>
               <InputFile OnChange = ""OnFileChange"" style=""max-width:250px;display:inline-block"" class=""form-control""/>
               <Button OnClick = ""@Upload"" Color=""Color.Secondary"" IsAsync=""true"">数据导入</Button>
               {tableToolbarPopconfirmButtons}
        </TableToolbarTemplate>
    </Table>
</Row>

<style>
    .dialog-table .modal-body {{height: calc(100vh - 400px);
        overflow: hidden;
    }}
</style>

@code {{
    IBrowserFile File {{get; set; }}
    Table<{razor.ClassName}> Table {{get; set; }}
    List<{razor.ClassName}>? SelectedItems {{get; set; }} = new List<{razor.ClassName}>();
    {razor.ClassName} SearchModel {{get; set; }} = new {razor.ClassName}();
    InsertRowMode InsertMode {{get; set; }} = InsertRowMode.Last;
    static IEnumerable<int> PageItemsSource => new int[] {{50, 100, 200, 300, 400, 500 }};

    [Inject] [NotNull] ITableExcelExport? Exporter {{get; set; }}
    [Inject] ToastService? toastService {{get; set; }}
    [Inject] IJSRuntime jsRuntime {{get; set; }}
    [Inject] IReportRepository Repository {{get; set; }}
    [Inject] IWebHostEnvironment env {{get; set; }}

    [Parameter] public string UserId {{get; set; }}
    [Parameter] public int Height {{get; set; }}

    async Task OnFileChange(InputFileChangeEventArgs e) => this.File = e.File;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {{
        if (firstRender)
        {{
            try
            {{
                var h = await jsRuntime.InvokeAsync<double>(""getHeight"");
                Height = Convert.ToInt32(h * 0.9);
                this.StateHasChanged();
            }}
            catch (Exception ex)
            {{
                throw;
            }}
        }}
    }}
    
    async Task Upload()
    {{
        if (this.File == null)
        {{
            toastService?.Error(""异常提示"",""请先选择文件"");
            return;
        }}
        long maxFileSize = 1024 * 1000 * 1000;
        using var content = new MultipartFormDataContent();
        var file = this.File;
        var fileContent = new StreamContent(file.OpenReadStream(maxFileSize));

        fileContent.Headers.ContentType =
            new MediaTypeHeaderValue(file.ContentType);

        content.Add(
            content: fileContent,
            name: ""files"",
            fileName: file.Name);
        try
        {{

            var result = await Http.PostAsync(""FileManager"", content);
            var uploadResponse = await result.Content.ReadFromJsonAsync<UploadResponse>();

            if (uploadResponse.ErrorCode == 0)
            {{
                var path = uploadResponse.FileName;
                var datas = ExcelHelper.ParseExcelToListNoUserId<Fact_Sales_GMVTargetTotal>(path);

                var updateDatas = datas.Where(w => w.Id > 0).ToList();
                if (updateDatas.Any())
                {{
                    var ids = string.Join("","", updateDatas.Select(s => s.Id));
                    updateDatas.ForEach(f =>
                    {{
                        f.Updater = UserId;
                        f.UpdateDate = DateTime.Now;
                    }});
                    var effectedRow = await Repository.Update_Fact_Sales_GMVTargetTotal(updateDatas);
                    if (effectedRow > 0)
                    {{
                        toastService?.Success(""提示"",$""Id:{{ids}},更新成功"");
                    }}
                    else
                    {{
                        toastService?.Error(""异常提示"",$""Id:{{ids}},更新失败"");
                    }}
                }}

                var insertDatas = datas.Where(w => w.Id == 0).ToList();
                if (insertDatas.Any())
                {{
                    insertDatas.ForEach(f =>
                    {{
                        f.Creater = UserId;
                        f.CreateDate = DateTime.Now;
                    }});
                    var effectedRow = await Repository.Add_Fact_Sales_GMVTargetTotal(insertDatas);
                    if (effectedRow > 0)
                    {{
                        toastService?.Success(""提示"",""上传成功"");
                    }}
                    else
                    {{
                        toastService?.Error(""异常提示"",""上传失败"");
                    }}
                }}
            }}
            else
            {{
                toastService?.Error(""异常提示"",""上传失败: "" + uploadResponse?.ErrorMsg);
            }}
        }}
        catch (Exception ex)
        {{
            toastService?.Error(""异常提示"", ""上传失败: "" + ex);
        }}
    }}
    
    async Task<bool> OnSaveAsync({razor.ClassName} item, ItemChangedType changedType)
    {{
        var resultFlag = false;
        if (changedType == ItemChangedType.Add)
        {{
            item.Creater = UserId;
            item.CreateDate = DateTime.Now;
            var result = await Repository.Add_{razor.ClassName}(new List<{razor.ClassName}>() {{item}});
            resultFlag = result == null ? false : true;
        }}
        else
        {{
            item.Updater = UserId;
            item.UpdateDate = DateTime.Now;
            var result = await Repository.Update_{razor.ClassName}(new List<{razor.ClassName}>() {{item}});
            resultFlag = result == 0 ? false : true;
        }}
        return resultFlag;
    }}

    async Task<QueryData<{razor.ClassName}>> OnQueryAsync(QueryPageOptions options)
    {{
        var result = await Repository.Query_{razor.ClassName}(options);
        var items = result.datas.AsEnumerable();
        if (!string.IsNullOrEmpty(options.SearchText))
        {{
            var txt = options.SearchText.ToLower();
            items = items.Where(i =>
                    {searchTxt}
                    );
        }}
        return new QueryData<Fact_Sales_GMVTargetTotal>()
        {{
            Items = items,
            TotalCount = result.total,
            IsSorted = true,
            IsFiltered = true,
            IsSearch = true
        }};
    }}

    async Task<bool> OnExportAsync(ITableExportDataContext<{razor.ClassName}> context)
    {{
        context.Options.PageItems = 50000;
        var datas = await OnQueryAsync(context.Options);
        var ret = await Exporter.ExportAsync(datas.Items, context.Columns);
        return ret;
    }}

    async Task<bool> OnDeleteAsync(IEnumerable<{razor.ClassName}> items)
    {{
        if (!items.Any())
        {{
            toastService?.Error(""请先选择数据"");
            return false;
        }}
        var result = await Repository.Delete_{razor.ClassName}(items.ToList());
        return result == 0 ? false : true;
    }}

    {tableToolbarPopconfirmFunction}
}}
");

                sw.Close(); //关闭文件
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static void BuildCS(CS cs)
        {
            try
            {
                var unit = new CodeCompileUnit();
                var ns = new CodeNamespace();
                if (cs.IsClass) ns = new CodeNamespace("JK.TitanData.Repository");
                if (cs.IsInterface) ns = new CodeNamespace("JK.TitanData.IRepository");

                // 构建using
                InitUsing(cs, ns);

                var fileName = cs.IsClass ? $"{cs.ClassName}Repository" : $"I{cs.ClassName}Repository";

                // 构建class/Interface
                var cls = new CodeTypeDeclaration(fileName)
                {
                    IsClass = cs.IsClass,
                    IsInterface = cs.IsInterface
                };
                if (cls.IsClass) cls.TypeAttributes = TypeAttributes.Public;
                if (cls.IsInterface) cls.TypeAttributes = TypeAttributes.Public | TypeAttributes.Interface;

                ns.Types.Add(cls);
                unit.Namespaces.Add(ns);

                // 构建Methods
                cls.Members.AddRange(InitMethod(cs));

                if (cs.IsClass)
                {
                    // 构造函数
                    CodeConstructor ctr = new CodeConstructor();
                    foreach (var property in cs.CtorProperties)
                    {
                        ctr.Parameters.Add(new CodeParameterDeclarationExpression(property.PropertyType, property.PropertyName));
                        ctr.Statements.Add(new CodeSnippetStatement($@"this.db = db;"));
                    }
                    cls.Members.Add(ctr);

                    // 构建Fields
                    foreach (var field in cs.Fields)
                    {
                        CodeMemberField fd = new CodeMemberField(field.FieldType, field.FieldName);
                        fd.Attributes = MemberAttributes.Private;
                        cls.Members.Add(fd);
                    }

                    // 构建继承
                    CodeTypeDeclaration dec = new CodeTypeDeclaration($"I{fileName}") { IsInterface = true };
                    cls.BaseTypes.Add(new CodeTypeReference(dec.Name));
                }

                var fileDir = cs.IsClass ? $"JK.TitanData.Repository" : $"JK.TitanData.IRepository";
                var scFile = $@"{Path.GetFullPath("../..")}\JK.TitanData\{fileDir}\{fileName}.cs";
                using (System.IO.StreamWriter sw = new System.IO.StreamWriter(scFile))
                {
                    var provider = CodeDomProvider.CreateProvider("CSharp");
                    var options = new CodeGeneratorOptions();
                    options.BracingStyle = "C";
                    options.BlankLinesBetweenMembers = true;
                    provider.GenerateCodeFromCompileUnit(unit, sw, options);
                    sw.Flush();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static void InitUsing(CS cs, CodeNamespace ns)
        {
            if (cs.IsClass)
            {
                ns.Imports.Add(new CodeNamespaceImport("JK.TitanData.IRepository"));
                ns.Imports.Add(new CodeNamespaceImport("SqlSugar"));

            }
            ns.Imports.Add(new CodeNamespaceImport("JK.TitanData.Entity"));
            ns.Imports.Add(new CodeNamespaceImport("BootstrapBlazor.Components"));
        }
        private static CodeMemberMethod[] InitMethod(CS cs)
        {
            var codeMemberMethods = new List<CodeMemberMethod>();
            foreach (var method in cs.Methods)
            {
                var codeMemberMethod = new CodeMemberMethod();
                switch (method.MethodType)
                {
                    case "Add":
                        codeMemberMethod = InitAddMethod(method, cs);
                        break;
                    case "Delete":
                        codeMemberMethod = InitDeleteMethod(method, cs);
                        break;
                    case "Update":
                        codeMemberMethod = InitUpdateMethod(method, cs);
                        break;
                    case "Query":
                        codeMemberMethod = InitQueryMethod(method, cs);
                        break;
                    case "Proc":
                        codeMemberMethod = InitProcMethod(method, cs);
                        break;
                }
                codeMemberMethods.Add(codeMemberMethod);
            }
            return codeMemberMethods.ToArray();
        }
        private static CodeMemberMethod InitProcMethod(Method method, CS cs)
        {
            var mth = new CodeMemberMethod();
            mth.Name = method.MethodName;

            if (method.Parameter != null && method.Parameter.Any() && method.Parameter.Count > 1)
            {
                if (cs.IsClass)
                {
                    mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                    mth.Statements.Add(new CodeSnippetStatement($@"return await db.Ado.UseStoredProcedure().ExecuteCommandAsync(procName, parameters);"));
                }
            }
            else
            {
                if (cs.IsClass)
                {
                    mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                    mth.Statements.Add(new CodeSnippetStatement($@"return await db.Ado.UseStoredProcedure().ExecuteCommandAsync(procName);"));
                }
            }
            foreach (KeyValuePair<string, string> item in method.Parameter)
            {
                mth.Parameters.Add(new CodeParameterDeclarationExpression(item.Key, item.Value));
            }
            if (cs.IsClass) mth.ReturnType = new CodeTypeReference($"async Task<{method.ReturnType}>");
            if (cs.IsInterface) mth.ReturnType = new CodeTypeReference($"Task<{method.ReturnType}>");

            return mth;
        }
        private static CodeMemberMethod InitAddMethod(Method method, CS cs)
        {
            var mth = new CodeMemberMethod();
            mth.Name = $"Add_{cs.ClassName}";
            foreach (KeyValuePair<string, string> item in method.Parameter)
            {
                mth.Parameters.Add(new CodeParameterDeclarationExpression(item.Key, item.Value));
            }
            if (cs.IsClass) mth.ReturnType = new CodeTypeReference($"async Task<{method.ReturnType}>");
            if (cs.IsInterface) mth.ReturnType = new CodeTypeReference($"Task<{method.ReturnType}>");

            if (cs.IsClass)
            {
                mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                mth.Statements.Add(new CodeSnippetStatement($"return await db.Fastest<{cs.ClassName}>().BulkCopyAsync(datas);"));
            }

            return mth;
        }
        private static CodeMemberMethod InitDeleteMethod(Method method, CS cs)
        {
            var mth = new CodeMemberMethod();
            mth.Name = $"Delete_{cs.ClassName}";
            foreach (KeyValuePair<string, string> item in method.Parameter)
            {
                mth.Parameters.Add(new CodeParameterDeclarationExpression(item.Key, item.Value));
            }
            if (cs.IsClass) mth.ReturnType = new CodeTypeReference($"async Task<{method.ReturnType}>");
            if (cs.IsInterface) mth.ReturnType = new CodeTypeReference($"Task<{method.ReturnType}>");

            if (cs.IsClass)
            {
                mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                mth.Statements.Add(new CodeSnippetStatement($@"if (datas.Any())
{{
    return await db.Deleteable(datas).ExecuteCommandAsync();
}}else{{
    return await db.Deleteable<{cs.ClassName}>().ExecuteCommandAsync();
}}"));
            }

            return mth;
        }
        private static CodeMemberMethod InitUpdateMethod(Method method, CS cs)
        {
            var mth = new CodeMemberMethod();
            mth.Name = $"Update_{cs.ClassName}";
            foreach (KeyValuePair<string, string> item in method.Parameter)
            {
                mth.Parameters.Add(new CodeParameterDeclarationExpression(item.Key, item.Value));
            }
            if (cs.IsClass) mth.ReturnType = new CodeTypeReference($"async Task<{method.ReturnType}>");
            if (cs.IsInterface) mth.ReturnType = new CodeTypeReference($"Task<{method.ReturnType}>");

            if (cs.IsClass)
            {
                mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                mth.Statements.Add(new CodeSnippetStatement($"return await db.Fastest<{cs.ClassName}>().BulkUpdateAsync(datas);"));
            }

            return mth;
        }
        private static CodeMemberMethod InitQueryMethod(Method method, CS cs)
        {
            var mth = new CodeMemberMethod();
            mth.Name = $"Query_{cs.ClassName}";
            foreach (KeyValuePair<string, string> item in method.Parameter)
            {
                mth.Parameters.Add(new CodeParameterDeclarationExpression(item.Key, item.Value));
            }
            if (cs.IsClass) mth.ReturnType = new CodeTypeReference($"async Task<{method.ReturnType}>");
            if (cs.IsInterface) mth.ReturnType = new CodeTypeReference($"Task<{method.ReturnType}>");

            if (cs.IsClass)
            {
                var filter = "";
                var assembly = Assembly.LoadFrom(@"D:\Work\Project\JK.TitanData\JK.TitanData.Entity\bin\Debug\net6.0\JK.TitanData.Entity.dll");
                var type = assembly.GetType($"JK.TitanData.Entity.{cs.ClassName}");
                var instance = Activator.CreateInstance(type);
                if (instance != null)
                {
                    var properties = instance.GetType().GetProperties();
                    foreach (var property in properties)
                    {
                        filter += $".WhereIF(!string.IsNullOrEmpty(model.{property.Name}.ToString()), w => w.{property.Name} == model.{property.Name})";
                        filter += "\r\n";
                    }
                    filter = filter.Substring(0, filter.Length - 2);
                }
                mth.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                mth.Statements.Add(new CodeSnippetStatement($@"RefAsync<int> total = 0;
var model = ({cs.ClassName})options.SearchModel;
var datas = await db.Queryable<{cs.ClassName}>()
{filter}
.ToPageListAsync(options.PageIndex, options.PageItems, total);
return new {method.ReturnType}() {{total = total,datas = datas}};"));
            }

            return mth;
        }

        #region 很麻烦(弃用)
        //public static void WriteCS(CS cs)
        //{
        //    try
        //    {
        //        var filePath = $@"{Path.GetFullPath("../..")}\JK.TitanData\JK.TitanData.IRepository\IReportRepository.cs";
        //        //var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
        //        var methodStr = "";
        //        var methods = cs.Methods;
        //        foreach (var method in methods)
        //        {
        //            if (method.MethodType == "Add")
        //            {
        //                methodStr += $@"Task<int> Add_{cs.ClassName}(System.Collections.Generic.List<JK.TitanData.Entity.{cs.ClassName}> datas);";
        //                methodStr += "\r\n";
        //            }
        //            if (method.MethodType == "Delete")
        //            {
        //                methodStr += $@"Task<int> Delete_{cs.ClassName}(System.Collections.Generic.List<JK.TitanData.Entity.{cs.ClassName}> datas);";
        //                methodStr += "\r\n";
        //            }
        //            if (method.MethodType == "Update")
        //            {
        //                methodStr += $@"Task<int> Update_{cs.ClassName}(System.Collections.Generic.List<JK.TitanData.Entity.{cs.ClassName}> datas);";
        //                methodStr += "\r\n";
        //            }
        //            if (method.MethodType == "Query")
        //            {
        //                methodStr += $@"Task<SalesCommissions<{cs.ClassName}>> Query_{cs.ClassName}(BootstrapBlazor.Components.QueryPageOptions options);";
        //                methodStr += "\r\n";
        //            }
        //            if (method.MethodType == "Proc")
        //            {
        //                string paramters = "";
        //                foreach (KeyValuePair<string, string> item in method.Parameter)
        //                {
        //                    paramters += $"{item.Key} {item.Value},";
        //                }
        //                paramters = paramters.TrimEnd(',');
        //                methodStr += $@"Task<{method.ReturnType}> {method.MethodName}({paramters}); ";
        //                methodStr += "\r\n";
        //            }
        //        }
        //        FileAdd(filePath, methodStr);
        //    }
        //    catch (Exception ex)
        //    {

        //        throw;
        //    }
        //}
        //public static void FileAdd(string Path, string strings)
        //{
        //    string[] lines = File.ReadAllLines(Path);
        //    foreach (string line in lines)
        //    {

        //    }
        //    StreamWriter sw = File.AppendText(Path);
        //    sw.Write(strings);
        //    sw.Flush();
        //    sw.Close();
        //    sw.Dispose();
        //} 
        #endregion
    }

    public class Razor
    {
        /// <summary>
        /// 菜单路径
        /// </summary>
        [Display(Name = "菜单路径")]
        public string PagePath { get; set; }

        /// <summary>
        /// 菜单中文名称
        /// </summary>
        [Display(Name = "菜单中文名称")]
        public string PageName { get; set; }

        /// <summary>
        /// 类名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 表格属性
        /// </summary>
        [Display(Name = "表格属性")]
        public Razor_Table_Property Table_Property { get; set; }

        /// <summary>
        /// 表格Toolbar
        /// </summary>
        [Display(Name = "表格Toolbar")]
        public List<Razor_Table_Toolbar> Table_Toolbars { get; set; } = new List<Razor_Table_Toolbar>();
    }
    public class Razor_Table_Toolbar
    {
        /// <summary>
        /// 按钮名称
        /// </summary>
        [Display(Name = "按钮名称")]
        public string BtnName { get; set; }

        /// <summary>
        /// 存储过程名称
        /// </summary>
        [Display(Name = "存储过程名称")]
        public string ProcName { get; set; }

        /// <summary>
        /// 存储过程参数
        /// </summary>
        [Display(Name = "存储过程参数")]
        public Dictionary<string, string> ProcParameters { get; set; }

        /// <summary>
        /// 存储过程返回值类型
        /// </summary>
        [Display(Name = "存储过程返回值类型")]
        public string ReturnType { get; set; }

        /// <summary>
        /// 按钮颜色(None / Active / Primary / Secondary / Success / Danger / Warning / Info / Light / Dark / Link)
        /// </summary>
        [Display(Name = "按钮颜色")]
        public string BtnColor { get; set; }
    }
    public class Razor_Table_PropertyViewModel
    {
        /// <summary>
        /// 双击编辑
        /// </summary>
        [Display(Name = "双击编辑")]
        public string DoubleClickToEdit { get; set; }

        /// <summary>
        /// 显示搜索框
        /// </summary>
        [Display(Name = "显示搜索框")]
        public string ShowSearch { get; set; }

        /// <summary>
        /// 显示删除
        /// </summary>
        [Display(Name = "显示删除")]
        public string ShowDeleteButton { get; set; }

        /// <summary>
        /// 显示行删除
        /// </summary>
        [Display(Name = "显示行删除")]
        public string ShowExtendDeleteButton { get; set; }

        /// <summary>
        /// 显示编辑
        /// </summary>
        [Display(Name = "显示编辑")]
        public string ShowEditButton { get; set; }

        /// <summary>
        /// 显示行编辑
        /// </summary>
        [Display(Name = "显示行编辑")]
        public string ShowExtendEditButton { get; set; }

        /// <summary>
        /// 显示新建
        /// </summary>
        [Display(Name = "显示新建")]
        public string ShowAddButton { get; set; }
    }
    public class Razor_Table_Property
    {
        /// <summary>
        /// 双击编辑
        /// </summary>
        [Display(Name = "双击编辑")]
        public bool DoubleClickToEdit { get; set; }

        /// <summary>
        /// 显示搜索框
        /// </summary>
        [Display(Name = "显示搜索框")]
        public bool ShowSearch { get; set; }

        /// <summary>
        /// 显示删除
        /// </summary>
        [Display(Name = "显示删除")]
        public bool ShowDeleteButton { get; set; }

        /// <summary>
        /// 显示行删除
        /// </summary>
        [Display(Name = "显示行删除")]
        public bool ShowExtendDeleteButton { get; set; }

        /// <summary>
        /// 显示编辑
        /// </summary>
        [Display(Name = "显示编辑")]
        public bool ShowEditButton { get; set; }

        /// <summary>
        /// 显示行编辑
        /// </summary>
        [Display(Name = "显示行编辑")]
        public bool ShowExtendEditButton { get; set; }

        /// <summary>
        /// 显示新建
        /// </summary>
        [Display(Name = "显示新建")]
        public bool ShowAddButton { get; set; }
    }

    /// <summary>
    /// CS
    /// </summary>
    public class CS
    {
        public CS()
        {
            this.Usings = new List<string>();
            this.Methods = new List<Method>();
            this.Fields = new List<Field>();
            this.Properties = new List<Property>();
            this.CtorProperties = new List<Property>();
        }

        /// <summary>
        /// using集合
        /// </summary>
        public List<string> Usings { get; set; }

        /// <summary>
        /// 类名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 方法集合
        /// </summary>
        public List<Method> Methods { get; set; }

        /// <summary>
        /// 属性集合
        /// </summary>
        public List<Property> Properties { get; set; }

        /// <summary>
        /// 字段集合
        /// </summary>
        public List<Field> Fields { get; set; }

        /// <summary>
        /// 构造函数属性集合
        /// </summary>
        public List<Property> CtorProperties { get; set; }

        /// <summary>
        /// 是否是Class
        /// </summary>
        public bool IsClass { get; set; }

        /// <summary>
        /// 是否是Interface
        /// </summary>
        public bool IsInterface { get; set; }
    }

    /// <summary>
    /// 字段
    /// </summary>
    public class Field
    {
        public string FieldName { get; set; }
        public Type FieldType { get; set; }
    }

    /// <summary>
    /// 属性
    /// </summary>
    public class Property
    {
        public string PropertyName { get; set; }
        public Type PropertyType { get; set; }
    }

    /// <summary>
    /// 方法
    /// </summary>
    public class Method
    {
        /// <summary>
        /// 参数
        /// </summary>
        public Dictionary<string, string> Parameter { get; set; }

        /// <summary>
        /// 返回值类型
        /// </summary>
        public string ReturnType { get; set; }

        /// <summary>
        /// 方法类型
        /// </summary>
        public string MethodType { get; set; }

        /// <summary>
        /// 方法名称
        /// </summary>
        public string MethodName { get; set; }
    }
}

调用
@page "/report/Component_Setting"

<Button OnClick="@InitSetting" Color="Color.Primary" IsAsync="true">自动生成</Button>

<style>
    .dialog-table .modal-body {
        height: calc(100vh - 400px);
        overflow: hidden;
    }
</style>

@using JK.TitanData.Util
@using SqlSugar
@using static JK.TitanData.Util.AutoBuildHelper
@code {

    [Inject] IReportRepository Repository { get; set; }
    void InitSetting()
    {
        var className = "Fact_Sales_GMVTargetTotal";
        var razor = InitRazor(className);

        InitInterface(className, razor);
        InitClass(className, razor);

        AutoBuildHelper.BuildRazor(razor);
    }

    void InitInterface(string className, Razor razor)
    {
        CS cs = new CS() { IsInterface = true, ClassName = className };
        

        cs.Methods.Add(new Method()
            {
                MethodType = "Add",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Delete",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Update",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Query",
                Parameter = new Dictionary<string, string>() { { "QueryPageOptions", "options" } },
                ReturnType = $"SalesCommissions<{cs.ClassName}>",
            });

        foreach (var item in razor.Table_Toolbars)
        {
            if (item.ProcParameters !=null && item.ProcParameters.Any())
            {
                cs.Methods.Add(new Method()
                    {
                        MethodName = item.ProcName,
                        MethodType = "Proc",
                        Parameter = new Dictionary<string, string>() { {"string","procName"},{ "List<SugarParameter>", "parameters" } },
                        ReturnType = item.ReturnType,
                    });
            }
            else
            {
                cs.Methods.Add(new Method()
                    {
                        MethodName = item.ProcName,
                        MethodType = "Proc",
                        Parameter = new Dictionary<string, string>() { {"string","procName"} },
                        ReturnType = item.ReturnType,
                    });
            }
        }
        AutoBuildHelper.BuildCS(cs);
    }

    void InitClass(string className, Razor razor)
    {
        CS cs = new CS() { IsClass = true, ClassName = className };

        cs.CtorProperties.Add(new Property()
            {
                PropertyName = "db",
                PropertyType = typeof(ISqlSugarClient)
            });

        cs.Fields.Add(new Field()
            {
                FieldName = "db",
                FieldType = typeof(ISqlSugarClient)
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Add",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Delete",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Update",
                Parameter = new Dictionary<string, string>() { { "List<Fact_Sales_GMVTargetTotal>", "datas" } },
                ReturnType = "int",
            });

        cs.Methods.Add(new Method()
            {
                MethodType = "Query",
                Parameter = new Dictionary<string, string>() { { "QueryPageOptions", "options" } },
                ReturnType = $"SalesCommissions<{cs.ClassName}>",
            });

        foreach (var item in razor.Table_Toolbars)
        {
            if (item.ProcParameters !=null && item.ProcParameters.Any())
            {
                cs.Methods.Add(new Method()
                    {
                        MethodName = item.ProcName,
                        MethodType = "Proc",
                        Parameter = new Dictionary<string, string>() { {"string","procName"},{ "List<SugarParameter>", "parameters" } },
                        ReturnType = item.ReturnType,
                    });
            }
            else
            {
                cs.Methods.Add(new Method()
                    {
                        MethodName = item.ProcName,
                        MethodType = "Proc",
                        Parameter = new Dictionary<string, string>() { {"string","procName"} },
                        ReturnType = item.ReturnType,
                    });
            }
        }
        AutoBuildHelper.BuildCS(cs);
        //AutoBuildHelper.WriteCS(cs);
    }

    Razor InitRazor(string className)
    {
        Razor razor = new Razor();
        razor.PagePath = "/report/Fact_Sales_GMVTargetTotal2";
        razor.PageName = "销售目标达成";
        razor.ClassName = className;
        razor.Table_Property = new Razor_Table_Property()
            {
                DoubleClickToEdit = true,
                ShowSearch = true,

                ShowDeleteButton = true,
                ShowExtendDeleteButton = true,

                ShowEditButton = true,
                ShowExtendEditButton = true,

                ShowAddButton = true
            };

        razor.Table_Toolbars.Add(new Razor_Table_Toolbar()
            {
                BtnName = "同步至参谋部数据库",
                ProcName = "P_TitanData_Sales_GMVTargetTotal",
                ReturnType = "int",
                BtnColor = "Color.Warning"
            });

        return razor;
    }

}