【重构】重构LubanAssistant代码,复用Luban的解析方式
parent
953c4db678
commit
3b17094618
|
|
@ -17,8 +17,8 @@
|
||||||
|
|
||||||
## 介绍
|
## 介绍
|
||||||
|
|
||||||
目前主流的配置工具功能多为excel文件到json之类格式的转换工具及简单代码生成器,只能勉强满足中小类型项目的需求。
|
|
||||||
在中大型游戏项目中,基本都会有技能、行为树之类的复杂功能。这些功能有非常复杂的数据结构,往往使用自定义编辑器制作,并以json、xml等文件格式保存。就算常规的excel表,也经常出现复杂的数据结构需求。这些简单工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响设计和开发效率。
|
在中大型游戏项目中,就算常规的excel表也经常出现复杂的数据结构需求,常规的导表工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响设计和开发效率。另外有复杂GamePlay的游戏,基本都会有技能、行为树、关卡之类的复杂功能,这些功能有非常复杂的数据结构,往往使用自定义编辑器制作,并以json、xml等文件格式保存,以excel为中心的导表工具无法处理这些数据,导致程序往往不得不手动解析它们,浪费了很多时间。
|
||||||
|
|
||||||
luban相较于常规的excel导表工具有以下核心优势:
|
luban相较于常规的excel导表工具有以下核心优势:
|
||||||
- 增强了excel格式。可以比较简洁地excel配置**任意复杂**的数据,像子结构、结构列表,以及更复杂的深层次的嵌套结构都能直接解析处理。
|
- 增强了excel格式。可以比较简洁地excel配置**任意复杂**的数据,像子结构、结构列表,以及更复杂的深层次的嵌套结构都能直接解析处理。
|
||||||
|
|
|
||||||
|
|
@ -1,350 +0,0 @@
|
||||||
//using Luban.Common.Utils;
|
|
||||||
//using Luban.Job.Cfg.Datas;
|
|
||||||
//using Luban.Job.Cfg.DataSources.Excel;
|
|
||||||
//using Luban.Job.Cfg.Defs;
|
|
||||||
//using Luban.Job.Cfg.TypeVisitors;
|
|
||||||
//using Luban.Job.Common.Types;
|
|
||||||
//using Luban.Job.Common.TypeVisitors;
|
|
||||||
//using System;
|
|
||||||
//using System.Collections.Generic;
|
|
||||||
|
|
||||||
//namespace Luban.Job.Cfg.DataCreators
|
|
||||||
//{
|
|
||||||
// class ExcelNamedRowDataCreator : ITypeFuncVisitor<TitleRow, bool, bool, DType>
|
|
||||||
// {
|
|
||||||
// public static ExcelNamedRowDataCreator Ins { get; } = new ExcelNamedRowDataCreator();
|
|
||||||
|
|
||||||
|
|
||||||
// public DType ReadExcel(TitleRow row, TBean btype)
|
|
||||||
// {
|
|
||||||
// return Accept(btype, row, false, false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TBool type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TByte type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TShort type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TFshort type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TInt type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TFint type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TLong type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TFlong type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TFloat type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TDouble type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TEnum type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TString type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TBytes type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TText type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private static bool IsContainerAndElementNotSepType(TType type)
|
|
||||||
// {
|
|
||||||
// switch (type)
|
|
||||||
// {
|
|
||||||
// case TArray ta: return ta.ElementType.Apply(IsNotSepTypeVisitor.Ins);
|
|
||||||
// case TList tl: return tl.ElementType.Apply(IsNotSepTypeVisitor.Ins);
|
|
||||||
// case TSet ts: return ts.ElementType.Apply(IsNotSepTypeVisitor.Ins);
|
|
||||||
// case TMap tm: return tm.KeyType.Apply(IsNotSepTypeVisitor.Ins) && tm.ValueType.Apply(IsNotSepTypeVisitor.Ins);
|
|
||||||
// default: return false;
|
|
||||||
// }
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private List<DType> CreateBeanFields(DefBean bean, TitleRow row)
|
|
||||||
// {
|
|
||||||
// var list = new List<DType>();
|
|
||||||
// foreach (DefField f in bean.HierarchyFields)
|
|
||||||
// {
|
|
||||||
// string fname = f.Name;
|
|
||||||
// Title title = row.GetTitle(fname);
|
|
||||||
// if (title == null)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"bean:'{bean.FullName}' 缺失 列:'{fname}',请检查是否写错或者遗漏");
|
|
||||||
// }
|
|
||||||
// // 多级标题
|
|
||||||
// if (title.SubTitles.Count > 0)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// list.Add(f.CType.Apply(this, row.GetSubTitleNamedRow(fname), f.IsMultiRow, f.IsNullable));
|
|
||||||
// }
|
|
||||||
// catch (DataCreateException dce)
|
|
||||||
// {
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw;
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// var dce = new DataCreateException(e, $"列:{fname}");
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw dce;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// string sep = "";
|
|
||||||
// if (string.IsNullOrWhiteSpace(sep) && IsContainerAndElementNotSepType(f.CType))
|
|
||||||
// {
|
|
||||||
// sep = ";,";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (f.IsMultiRow)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (f.CType.IsCollection)
|
|
||||||
// {
|
|
||||||
// list.Add(f.CType.Apply(MultiRowExcelDataCreator.Ins, row.GetColumnOfMultiRows(f.Name, sep), f.IsNullable, (DefAssembly)bean.AssemblyBase));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// list.Add(f.CType.Apply(ExcelDataCreator.Ins, f, row.GetMultiRowStream(f.Name, sep), (DefAssembly)bean.AssemblyBase));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (DataCreateException dce)
|
|
||||||
// {
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw;
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// var dce = new DataCreateException(e, "");
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw dce;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// //ExcelStream stream = row.GetColumn(f.Name, sep, !f.CType.Apply(IsMultiData.Ins));
|
|
||||||
// ExcelStream stream = row.GetColumn(f.Name);
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// list.Add(f.CType.Apply(ExcelDataCreator.Ins, f, stream, (DefAssembly)bean.AssemblyBase));
|
|
||||||
// }
|
|
||||||
// catch (DataCreateException dce)
|
|
||||||
// {
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw;
|
|
||||||
// }
|
|
||||||
// catch (Exception e)
|
|
||||||
// {
|
|
||||||
// var dce = new DataCreateException(e, stream.LastReadDataInfo);
|
|
||||||
// dce.Push(bean, f);
|
|
||||||
// throw dce;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return list;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// public DType Accept(TBean type, TitleRow row, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// var originBean = (DefBean)type.Bean;
|
|
||||||
// if (originBean.IsAbstractType)
|
|
||||||
// {
|
|
||||||
// string subType = row.GetColumn(DefBean.TYPE_NAME_KEY).Read().ToString().Trim();
|
|
||||||
// if (subType.ToLower() == DefBean.BEAN_NULL_STR)
|
|
||||||
// {
|
|
||||||
// if (!type.IsNullable)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"type:'{type}' 不是可空类型 '{type.Bean.FullName}?' , 不能为空");
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// string fullType = TypeUtil.MakeFullName(originBean.Namespace, subType);
|
|
||||||
// DefBean implType = (DefBean)originBean.GetNotAbstractChildType(subType);
|
|
||||||
// if (implType == null)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"type:'{fullType}' 不是 bean 类型");
|
|
||||||
// }
|
|
||||||
// return new DBean(originBean, implType, CreateBeanFields(implType, row));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// if (type.IsNullable)
|
|
||||||
// {
|
|
||||||
// string subType = row.GetColumn(DefBean.TYPE_NAME_KEY).Read().ToString().Trim();
|
|
||||||
// if (subType == DefBean.BEAN_NULL_STR)
|
|
||||||
// {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// else if (subType != DefBean.BEAN_NOT_NULL_STR && subType != originBean.Name)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"type:'{type.Bean.FullName}' 可空标识:'{subType}' 不合法(只能为{DefBean.BEAN_NOT_NULL_STR}或{DefBean.BEAN_NULL_STR}或{originBean.Name})");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return new DBean(originBean, originBean, CreateBeanFields(originBean, row));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// private List<DType> ReadList(TBean elementType, TitleRow row, bool multirow)
|
|
||||||
// {
|
|
||||||
// var list = new List<DType>();
|
|
||||||
// // 如果是多行数据,以当前title为title,每行读入一个element
|
|
||||||
// if (multirow)
|
|
||||||
// {
|
|
||||||
// //foreach (var sub in row.GenerateSubNameRows(elementType))
|
|
||||||
// foreach (var sub in row.Elements)
|
|
||||||
// {
|
|
||||||
// list.Add(this.Accept(elementType, sub, false, false));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// // 如果不是多行,并且定义了子标题的话。以一个子标题所占的列,读入一个数据
|
|
||||||
|
|
||||||
// //foreach (var sub in row.SelfTitle.SubTitleList)
|
|
||||||
// //{
|
|
||||||
// // list.Add(this.Accept(elementType, new TitleRow(sub, row.Rows), false, false));
|
|
||||||
// //}
|
|
||||||
// throw new NotSupportedException("只有multi_rows=1的list,bean类型才允许有子title");
|
|
||||||
// }
|
|
||||||
// return list;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TArray type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// if (type.ElementType is not TBean bean)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"NamedRow 只支持 bean 类型的容器");
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return new DArray(type, ReadList(bean, x, multirow));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TList type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// if (type.ElementType is not TBean bean)
|
|
||||||
// {
|
|
||||||
// throw new Exception($"NamedRow 只支持 bean 类型的容器");
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return new DList(type, ReadList(bean, x, multirow));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TSet type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// private bool TryCreateColumnStream(TitleRow x, Title title, out ExcelStream stream)
|
|
||||||
// {
|
|
||||||
// var cells = new List<Cell>();
|
|
||||||
// for (int i = title.FromIndex; i <= title.ToIndex; i++)
|
|
||||||
// {
|
|
||||||
// foreach (var row in x.Rows)
|
|
||||||
// {
|
|
||||||
// if (row.Count > i)
|
|
||||||
// {
|
|
||||||
// var value = row[i].Value;
|
|
||||||
// if (!(value == null || (value is string s && string.IsNullOrEmpty(s))))
|
|
||||||
// {
|
|
||||||
// cells.Add(row[i]);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (cells.Count > 0)
|
|
||||||
// {
|
|
||||||
// stream = new ExcelStream(cells, 0, cells.Count - 1, "", false);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// stream = null;
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TMap type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// var map = new Dictionary<DType, DType>();
|
|
||||||
// foreach (var e in x.Fields)
|
|
||||||
// {
|
|
||||||
// var keyData = type.KeyType.Apply(StringDataCreator.Ins, e.Key);
|
|
||||||
// var valueData = type.ValueType.Apply(ExcelDataCreator.Ins, null, e.Value.AsStream, DefAssembly.LocalAssebmly);
|
|
||||||
// map.Add(keyData, valueData);
|
|
||||||
// }
|
|
||||||
// return new DMap(type, map);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TVector2 type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TVector3 type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TVector4 type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public DType Accept(TDateTime type, TitleRow x, bool multirow, bool nullable)
|
|
||||||
// {
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
@ -224,19 +224,27 @@ namespace Luban.Job.Cfg.DataCreators
|
||||||
|
|
||||||
public DType Accept(TText type, Sheet sheet, TitleRow row)
|
public DType Accept(TText type, Sheet sheet, TitleRow row)
|
||||||
{
|
{
|
||||||
if (row.CellCount != 2)
|
if (string.IsNullOrEmpty(row.SelfTitle.Sep))
|
||||||
{
|
{
|
||||||
throw new Exception($"text 要求两个字段");
|
if (row.CellCount != 2)
|
||||||
|
{
|
||||||
|
throw new Exception($"text 要求两个字段");
|
||||||
|
}
|
||||||
|
int startIndex = row.SelfTitle.FromIndex;
|
||||||
|
var key = ParseString(row.Row[startIndex].Value);
|
||||||
|
var text = ParseString(row.Row[startIndex + 1].Value);
|
||||||
|
if (type.IsNullable && key == null && text == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DataUtil.ValidateText(key, text);
|
||||||
|
return new DText(key, text);
|
||||||
}
|
}
|
||||||
int startIndex = row.SelfTitle.FromIndex;
|
else
|
||||||
var key = ParseString(row.Row[startIndex].Value);
|
|
||||||
var text = ParseString(row.Row[startIndex + 1].Value);
|
|
||||||
if (type.IsNullable && key == null && text == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
var s = row.AsStream("");
|
||||||
|
return type.Apply(ExcelStreamDataCreator.Ins, s);
|
||||||
}
|
}
|
||||||
DataUtil.ValidateText(key, text);
|
|
||||||
return new DText(key, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DType> CreateBeanFields(DefBean bean, Sheet sheet, TitleRow row)
|
private List<DType> CreateBeanFields(DefBean bean, Sheet sheet, TitleRow row)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,16 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Load(params RawSheet[] rawSheets)
|
||||||
|
{
|
||||||
|
foreach (RawSheet rawSheet in rawSheets)
|
||||||
|
{
|
||||||
|
var sheet = new Sheet("__intern__", rawSheet.TableName);
|
||||||
|
sheet.Load(rawSheet);
|
||||||
|
_sheets.Add(sheet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public RawSheetTableDefInfo LoadTableDefInfo(string rawUrl, string sheetName, Stream stream)
|
public RawSheetTableDefInfo LoadTableDefInfo(string rawUrl, string sheetName, Stream stream)
|
||||||
{
|
{
|
||||||
return SheetLoadUtil.LoadSheetTableDefInfo(rawUrl, sheetName, stream);
|
return SheetLoadUtil.LoadSheetTableDefInfo(rawUrl, sheetName, stream);
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,12 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
|
|
||||||
class RawSheet
|
class RawSheet
|
||||||
{
|
{
|
||||||
public Title Title { get; init; }
|
public Title Title { get; set; }
|
||||||
|
|
||||||
public List<List<Cell>> Cells { get; init; }
|
public string TableName { get; set; }
|
||||||
|
|
||||||
|
public int TitleRowCount { get; set; }
|
||||||
|
|
||||||
|
public List<List<Cell>> Cells { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,19 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
{
|
{
|
||||||
class FieldInfo
|
class FieldInfo
|
||||||
{
|
{
|
||||||
public string Name { get; init; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public Dictionary<string, string> Tags { get; init; }
|
public Dictionary<string, string> Tags { get; set; }
|
||||||
|
|
||||||
public string Type { get; init; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
public string BriefDesc { get; init; }
|
public string BriefDesc { get; set; }
|
||||||
|
|
||||||
public string DetailDesc { get; init; }
|
public string DetailDesc { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class RawSheetTableDefInfo
|
class RawSheetTableDefInfo
|
||||||
{
|
{
|
||||||
public Dictionary<string, FieldInfo> FieldInfos { get; init; }
|
public Dictionary<string, FieldInfo> FieldInfos { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,14 +67,14 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
bool orientRow;
|
bool orientRow;
|
||||||
int titleRowNum;
|
int titleRowNum;
|
||||||
|
|
||||||
if (!TryParseMeta(reader, out orientRow, out titleRowNum, out var _))
|
if (!TryParseMeta(reader, out orientRow, out titleRowNum, out var tableName))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var cells = ParseRawSheetContent(reader, orientRow);
|
var cells = ParseRawSheetContent(reader, orientRow);
|
||||||
var title = ParseTitle(cells, reader.MergeCells, orientRow, out _);
|
var title = ParseTitle(cells, reader.MergeCells, orientRow, out _);
|
||||||
cells.RemoveRange(0, Math.Min(titleRowNum, cells.Count));
|
cells.RemoveRange(0, Math.Min(titleRowNum, cells.Count));
|
||||||
return new RawSheet() { Title = title, Cells = cells };
|
return new RawSheet() { Title = title, TitleRowCount = titleRowNum, TableName = tableName, Cells = cells };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetTitleRowNum(CellRange[] mergeCells, bool orientRow)
|
private static int GetTitleRowNum(CellRange[] mergeCells, bool orientRow)
|
||||||
|
|
@ -108,8 +108,10 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
|
|
||||||
public static Title ParseTitle(List<List<Cell>> cells, CellRange[] mergeCells, bool orientRow, out int titleRowNum)
|
public static Title ParseTitle(List<List<Cell>> cells, CellRange[] mergeCells, bool orientRow, out int titleRowNum)
|
||||||
{
|
{
|
||||||
var rootTitle = new Title() {
|
var rootTitle = new Title()
|
||||||
Root = true, Name = "__root__",
|
{
|
||||||
|
Root = true,
|
||||||
|
Name = "__root__",
|
||||||
Tags = new Dictionary<string, string>(),
|
Tags = new Dictionary<string, string>(),
|
||||||
FromIndex = 0,
|
FromIndex = 0,
|
||||||
ToIndex = cells.Select(r => r.Count).Max() - 1
|
ToIndex = cells.Select(r => r.Count).Max() - 1
|
||||||
|
|
@ -130,10 +132,14 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
|
|
||||||
private static bool IsIgnoreTitle(string title)
|
private static bool IsIgnoreTitle(string title)
|
||||||
{
|
{
|
||||||
|
#if !LUBAN_LITE
|
||||||
return string.IsNullOrEmpty(title) || title.StartsWith('#');
|
return string.IsNullOrEmpty(title) || title.StartsWith('#');
|
||||||
|
#else
|
||||||
|
return string.IsNullOrEmpty(title) || title.StartsWith("#");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (string Name, Dictionary<string, string> Tags) ParseNameAndMetaAttrs(string nameAndAttrs)
|
public static (string Name, Dictionary<string, string> Tags) ParseNameAndMetaAttrs(string nameAndAttrs)
|
||||||
{
|
{
|
||||||
var attrs = nameAndAttrs.Split('&');
|
var attrs = nameAndAttrs.Split('&');
|
||||||
|
|
||||||
|
|
@ -227,24 +233,20 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryParseMeta(IExcelDataReader reader, out bool orientRow, out int titleRows, out string tableName)
|
public static bool TryParseMeta(List<string> cells, out bool orientRow, out int titleRows, out string tableName)
|
||||||
{
|
{
|
||||||
orientRow = true;
|
orientRow = true;
|
||||||
titleRows = TITLE_DEFAULT_ROW_NUM;
|
titleRows = TITLE_DEFAULT_ROW_NUM;
|
||||||
tableName = "";
|
tableName = "";
|
||||||
if (!reader.Read() || reader.FieldCount == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// meta 行 必须以 ##为第一个单元格内容,紧接着 key:value 形式 表达meta属性
|
// meta 行 必须以 ##为第一个单元格内容,紧接着 key:value 形式 表达meta属性
|
||||||
if (reader.GetString(0) != "##")
|
if (cells.Count == 0 || cells[0] != "##")
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1, n = reader.FieldCount; i < n; i++)
|
foreach (var attr in cells.Skip(1))
|
||||||
{
|
{
|
||||||
var attr = reader.GetString(i)?.Trim();
|
|
||||||
if (string.IsNullOrWhiteSpace(attr))
|
if (string.IsNullOrWhiteSpace(attr))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -255,8 +257,8 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
{
|
{
|
||||||
throw new Exception($"单元薄 meta 定义出错. attribute:{attr}");
|
throw new Exception($"单元薄 meta 定义出错. attribute:{attr}");
|
||||||
}
|
}
|
||||||
string key = ss[0].Trim().ToLower();
|
string key = ss[0].Trim();
|
||||||
string value = ss[1].Trim().ToLower();
|
string value = ss[1].Trim();
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case "orientation":
|
case "orientation":
|
||||||
|
|
@ -291,6 +293,23 @@ namespace Luban.Job.Cfg.DataSources.Excel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TryParseMeta(IExcelDataReader reader, out bool orientRow, out int titleRows, out string tableName)
|
||||||
|
{
|
||||||
|
if (!reader.Read() || reader.FieldCount == 0)
|
||||||
|
{
|
||||||
|
orientRow = true;
|
||||||
|
titleRows = TITLE_DEFAULT_ROW_NUM;
|
||||||
|
tableName = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var cells = new List<string>();
|
||||||
|
for (int i = 0, n = reader.FieldCount; i < n; i++)
|
||||||
|
{
|
||||||
|
cells.Add(reader.GetString(i)?.Trim());
|
||||||
|
}
|
||||||
|
return TryParseMeta(cells, out orientRow, out titleRows, out tableName);
|
||||||
|
}
|
||||||
|
|
||||||
private static List<List<Cell>> ParseRawSheetContent(IExcelDataReader reader, bool orientRow, int? maxParseRow = null)
|
private static List<List<Cell>> ParseRawSheetContent(IExcelDataReader reader, bool orientRow, int? maxParseRow = null)
|
||||||
{
|
{
|
||||||
// TODO 优化性能
|
// TODO 优化性能
|
||||||
|
|
|
||||||
|
|
@ -301,8 +301,15 @@ namespace Luban.Job.Cfg.Defs
|
||||||
//var titleRow = sheet.RowColumns[sheet.AttrRowCount];
|
//var titleRow = sheet.RowColumns[sheet.AttrRowCount];
|
||||||
//// 有可能没有注释行,此时使用标题行,这个是必须有的
|
//// 有可能没有注释行,此时使用标题行,这个是必须有的
|
||||||
//var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow;
|
//var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow;
|
||||||
|
#if !LUBAN_LITE
|
||||||
foreach (var (name, f) in tableDefInfo.FieldInfos)
|
foreach (var (name, f) in tableDefInfo.FieldInfos)
|
||||||
{
|
{
|
||||||
|
#else
|
||||||
|
foreach (var e in tableDefInfo.FieldInfos)
|
||||||
|
{
|
||||||
|
var name = e.Key;
|
||||||
|
var f = e.Value;
|
||||||
|
#endif
|
||||||
var cf = new CfgField() { Name = name, Id = 0 };
|
var cf = new CfgField() { Name = name, Id = 0 };
|
||||||
|
|
||||||
string[] attrs = f.Type.Trim().Split('&').Select(s => s.Trim()).ToArray();
|
string[] attrs = f.Type.Trim().Split('&').Select(s => s.Trim()).ToArray();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
using Bright.Collections;
|
using Bright.Collections;
|
||||||
using Luban.Job.Cfg.Datas;
|
using Luban.Job.Cfg.Datas;
|
||||||
|
#if !LUBAN_LITE
|
||||||
using Luban.Job.Cfg.l10n;
|
using Luban.Job.Cfg.l10n;
|
||||||
|
#endif
|
||||||
using Luban.Job.Cfg.RawDefs;
|
using Luban.Job.Cfg.RawDefs;
|
||||||
using Luban.Job.Cfg.TypeVisitors;
|
using Luban.Job.Cfg.TypeVisitors;
|
||||||
using Luban.Job.Common.Defs;
|
using Luban.Job.Common.Defs;
|
||||||
|
|
@ -14,6 +16,8 @@ namespace Luban.Job.Cfg.Defs
|
||||||
{
|
{
|
||||||
public class TableDataInfo
|
public class TableDataInfo
|
||||||
{
|
{
|
||||||
|
public DefTable Table { get; }
|
||||||
|
|
||||||
public List<Record> MainRecords { get; }
|
public List<Record> MainRecords { get; }
|
||||||
|
|
||||||
public List<Record> PatchRecords { get; }
|
public List<Record> PatchRecords { get; }
|
||||||
|
|
@ -22,8 +26,9 @@ namespace Luban.Job.Cfg.Defs
|
||||||
|
|
||||||
public Dictionary<DType, Record> FinalRecordMap { get; set; }
|
public Dictionary<DType, Record> FinalRecordMap { get; set; }
|
||||||
|
|
||||||
public TableDataInfo(List<Record> mainRecords, List<Record> patchRecords)
|
public TableDataInfo(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
||||||
{
|
{
|
||||||
|
Table = table;
|
||||||
MainRecords = mainRecords;
|
MainRecords = mainRecords;
|
||||||
PatchRecords = patchRecords;
|
PatchRecords = patchRecords;
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +74,7 @@ namespace Luban.Job.Cfg.Defs
|
||||||
|
|
||||||
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
|
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
|
||||||
|
|
||||||
|
#if !LUBAN_LITE
|
||||||
public RawTextTable RawTextTable { get; } = new RawTextTable();
|
public RawTextTable RawTextTable { get; } = new RawTextTable();
|
||||||
|
|
||||||
public TextTable ExportTextTable { get; private set; }
|
public TextTable ExportTextTable { get; private set; }
|
||||||
|
|
@ -83,6 +89,8 @@ namespace Luban.Job.Cfg.Defs
|
||||||
NotConvertTextSet = new NotConvertTextSet();
|
NotConvertTextSet = new NotConvertTextSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
public Patch GetPatch(string name)
|
public Patch GetPatch(string name)
|
||||||
{
|
{
|
||||||
return _patches.Find(b => b.Name == name);
|
return _patches.Find(b => b.Name == name);
|
||||||
|
|
@ -103,7 +111,7 @@ namespace Luban.Job.Cfg.Defs
|
||||||
|
|
||||||
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
||||||
{
|
{
|
||||||
_recordsByTables[table.FullName] = new TableDataInfo(mainRecords, patchRecords);
|
_recordsByTables[table.FullName] = new TableDataInfo(table, mainRecords, patchRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Record> GetTableAllDataList(DefTable table)
|
public List<Record> GetTableAllDataList(DefTable table)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ namespace Luban.Job.Cfg.Defs
|
||||||
|| (CType is TList tl && tl.ElementType.IsBean)
|
|| (CType is TList tl && tl.ElementType.IsBean)
|
||||||
|| (CType is TMap tm && tm.ValueType.IsBean);
|
|| (CType is TMap tm && tm.ValueType.IsBean);
|
||||||
|
|
||||||
|
#if !LUBAN_LITE
|
||||||
public string CsRefTypeName
|
public string CsRefTypeName
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -95,6 +96,7 @@ namespace Luban.Job.Cfg.Defs
|
||||||
return $"{TsRefVarName} : {table.ValueTType.Apply(TypescriptDefineTypeNameVisitor.Ins)}{(IsNullable ? "" : " = undefined!")}";
|
return $"{TsRefVarName} : {table.ValueTType.Apply(TypescriptDefineTypeNameVisitor.Ins)}{(IsNullable ? "" : " = undefined!")}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public string CsRefVarName => $"{CsStyleName}_Ref";
|
public string CsRefVarName => $"{CsStyleName}_Ref";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Bright.Collections;
|
||||||
using Luban.Common.Utils;
|
using Luban.Common.Utils;
|
||||||
using Luban.Job.Cfg.Datas;
|
using Luban.Job.Cfg.Datas;
|
||||||
using Luban.Job.Cfg.DataVisitors;
|
using Luban.Job.Cfg.DataVisitors;
|
||||||
|
|
@ -86,10 +87,12 @@ namespace Luban.Job.Cfg
|
||||||
{
|
{
|
||||||
CurrentVisitor = visitor;
|
CurrentVisitor = visitor;
|
||||||
visitor.ValidateTable(t, records);
|
visitor.ValidateTable(t, records);
|
||||||
|
#if !LUBAN_LITE
|
||||||
if (this.Assembly.NeedL10nTextTranslate)
|
if (this.Assembly.NeedL10nTextTranslate)
|
||||||
{
|
{
|
||||||
ValidateText(t, records);
|
ValidateText(t, records);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -106,6 +109,7 @@ namespace Luban.Job.Cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !LUBAN_LITE
|
||||||
private void ValidateText(DefTable table, List<Record> records)
|
private void ValidateText(DefTable table, List<Record> records)
|
||||||
{
|
{
|
||||||
foreach (var r in records)
|
foreach (var r in records)
|
||||||
|
|
@ -115,6 +119,7 @@ namespace Luban.Job.Cfg
|
||||||
}
|
}
|
||||||
CurrentVisitor.CurrentValidateRecord = null;
|
CurrentVisitor.CurrentValidateRecord = null;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private async Task ValidatePaths()
|
private async Task ValidatePaths()
|
||||||
{
|
{
|
||||||
|
|
@ -165,7 +170,11 @@ namespace Luban.Job.Cfg
|
||||||
{
|
{
|
||||||
if (ls.All(f => fileNotExistsSet.Contains(f)))
|
if (ls.All(f => fileNotExistsSet.Contains(f)))
|
||||||
{
|
{
|
||||||
|
#if !LUBAN_LITE
|
||||||
agent.Error("记录 {0} = {1} (来自文件:{2}) 所引用文件:{3} 不存在", q.DataPath, q.Value, q.Source, string.Join(',', ls));
|
agent.Error("记录 {0} = {1} (来自文件:{2}) 所引用文件:{3} 不存在", q.DataPath, q.Value, q.Source, string.Join(',', ls));
|
||||||
|
#else
|
||||||
|
agent.Error("记录 {0} = {1} (来自文件:{2}) 所引用文件:{3} 不存在", q.DataPath, q.Value, q.Source, string.Join(",", ls));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -252,8 +261,10 @@ namespace Luban.Job.Cfg
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !LUBAN_LITE
|
||||||
tableDataInfo.FinalRecords = mainRecords;
|
tableDataInfo.FinalRecords = mainRecords;
|
||||||
tableDataInfo.FinalRecordMap = mainRecordMap;
|
tableDataInfo.FinalRecordMap = mainRecordMap;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,11 @@ namespace Luban.Job.Cfg.Validators
|
||||||
string suffix = groups[2].Value.Substring(1);
|
string suffix = groups[2].Value.Substring(1);
|
||||||
if (suffix.EndsWith("_C"))
|
if (suffix.EndsWith("_C"))
|
||||||
{
|
{
|
||||||
|
#if !LUBAN_LITE
|
||||||
suffix = suffix[0..^2];
|
suffix = suffix[0..^2];
|
||||||
|
#else
|
||||||
|
suffix = suffix.Substring(0, suffix.Length - 2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return path.EndsWith(suffix);
|
return path.EndsWith(suffix);
|
||||||
}
|
}
|
||||||
|
|
@ -212,9 +216,17 @@ namespace Luban.Job.Cfg.Validators
|
||||||
|
|
||||||
string patType = ss[0];
|
string patType = ss[0];
|
||||||
bool emptyAble = false;
|
bool emptyAble = false;
|
||||||
|
#if !LUBAN_LITE
|
||||||
if (patType.EndsWith('?'))
|
if (patType.EndsWith('?'))
|
||||||
|
#else
|
||||||
|
if (patType.EndsWith("?"))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !LUBAN_LITE
|
||||||
patType = patType[0..^1];
|
patType = patType[0..^1];
|
||||||
|
#else
|
||||||
|
patType = patType.Substring(0, patType.Length - 1);
|
||||||
|
#endif
|
||||||
emptyAble = true;
|
emptyAble = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,14 +82,22 @@ namespace Luban.Job.Cfg.Validators
|
||||||
case '(': _includeMinBound = false; break;
|
case '(': _includeMinBound = false; break;
|
||||||
default: ThrowError(); break;
|
default: ThrowError(); break;
|
||||||
}
|
}
|
||||||
|
#if !LUBAN_LITE
|
||||||
switch (_str[^1])
|
switch (_str[^1])
|
||||||
|
#else
|
||||||
|
switch (_str[_str.Length - 1])
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
case ']': _includeMaxBound = true; break;
|
case ']': _includeMaxBound = true; break;
|
||||||
case ')': _includeMaxBound = false; break;
|
case ')': _includeMaxBound = false; break;
|
||||||
default: ThrowError(); break;
|
default: ThrowError(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !LUBAN_LITE
|
||||||
var pars = _str[1..^1].Split(',');
|
var pars = _str[1..^1].Split(',');
|
||||||
|
#else
|
||||||
|
var pars = _str.Substring(1, _str.Length - 1).Split(',');
|
||||||
|
#endif
|
||||||
if (pars.Length != 2)
|
if (pars.Length != 2)
|
||||||
{
|
{
|
||||||
ThrowError();
|
ThrowError();
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,13 @@ namespace Luban.Job.Cfg.Validators
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DefTable ct = assembly.GetCfgTable(actualTable);
|
DefTable ct = assembly.GetCfgTable(actualTable);
|
||||||
|
#if !LUBAN_LITE
|
||||||
var recordMap = assembly.GetTableDataInfo(ct).FinalRecordMap;
|
var recordMap = assembly.GetTableDataInfo(ct).FinalRecordMap;
|
||||||
if (/*recordMap != null &&*/ recordMap.ContainsKey(key))
|
if (/*recordMap != null &&*/ recordMap.ContainsKey(key))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var table in Tables)
|
foreach (var table in Tables)
|
||||||
|
|
|
||||||
|
|
@ -98,11 +98,10 @@ namespace LubanAssistant
|
||||||
|
|
||||||
private void LoadDataToCurrentDoc()
|
private void LoadDataToCurrentDoc()
|
||||||
{
|
{
|
||||||
|
|
||||||
Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet;
|
Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet;
|
||||||
|
|
||||||
var metaAttrs = ExcelUtil.ParseMetaAttrs(sheet);
|
var rawSheet = ExcelUtil.ParseRawSheetTitleOnly(sheet);
|
||||||
if (!metaAttrs.TryGetValue("table", out var tableName))
|
if (string.IsNullOrWhiteSpace(rawSheet.TableName))
|
||||||
{
|
{
|
||||||
MessageBox.Show($"meta行未指定table名");
|
MessageBox.Show($"meta行未指定table名");
|
||||||
return;
|
return;
|
||||||
|
|
@ -112,9 +111,9 @@ namespace LubanAssistant
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tableDataInfo = LastLoadTableData = await DataLoaderUtil.LoadTableDataAsync(RootDefineFile, InputDataDir, tableName);
|
var tableDataInfo = LastLoadTableData = await DataLoaderUtil.LoadTableDataAsync(RootDefineFile, InputDataDir, rawSheet.TableName);
|
||||||
var title = ExcelUtil.ParseTitles(sheet);
|
var title = ExcelUtil.ParseTitles(sheet);
|
||||||
ExcelUtil.FillRecords(sheet, metaAttrs, title, tableDataInfo);
|
ExcelUtil.FillRecords(sheet, rawSheet.TitleRowCount, title, tableDataInfo);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -159,12 +158,13 @@ namespace LubanAssistant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveRecords(Action<Worksheet, Dictionary<string, string>, TableDataInfo, DefTable, TitleInfo> saveTask)
|
private void SaveRecords(Action<Worksheet, int, TableDataInfo, DefTable, Title> saveTask)
|
||||||
{
|
{
|
||||||
Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet;
|
Worksheet sheet = Globals.LubanAssistant.Application.ActiveSheet;
|
||||||
|
|
||||||
var metaAttrs = ExcelUtil.ParseMetaAttrs(sheet);
|
var rawSheet = ExcelUtil.ParseRawSheetTitleOnly(sheet);
|
||||||
if (!metaAttrs.TryGetValue("table", out var tableName))
|
string tableName = rawSheet.TableName;
|
||||||
|
if (string.IsNullOrWhiteSpace(tableName))
|
||||||
{
|
{
|
||||||
MessageBox.Show($"meta行未指定table名");
|
MessageBox.Show($"meta行未指定table名");
|
||||||
return;
|
return;
|
||||||
|
|
@ -181,7 +181,7 @@ namespace LubanAssistant
|
||||||
|
|
||||||
var tableDef = await DataLoaderUtil.LoadTableDefAsync(RootDefineFile, InputDataDir, tableName);
|
var tableDef = await DataLoaderUtil.LoadTableDefAsync(RootDefineFile, InputDataDir, tableName);
|
||||||
var title = ExcelUtil.ParseTitles(sheet);
|
var title = ExcelUtil.ParseTitles(sheet);
|
||||||
saveTask(sheet, metaAttrs, LastLoadTableData, tableDef, title);
|
saveTask(sheet, rawSheet.TitleRowCount, LastLoadTableData, tableDef, title);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -192,13 +192,13 @@ namespace LubanAssistant
|
||||||
|
|
||||||
private void BtnSaveAllClick(object sender, RibbonControlEventArgs e)
|
private void BtnSaveAllClick(object sender, RibbonControlEventArgs e)
|
||||||
{
|
{
|
||||||
SaveRecords((Worksheet sheet, Dictionary<string, string> metaAttrs, TableDataInfo tableDataInfo, DefTable defTable, TitleInfo title) =>
|
SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) =>
|
||||||
{
|
{
|
||||||
int usedRowNum = sheet.UsedRange.Rows.Count;
|
int usedRowNum = sheet.UsedRange.Rows.Count;
|
||||||
int firstDataRowNum = int.Parse(metaAttrs["title_rows"]) + 2;
|
int firstDataRowNum = titleRowNum + 2;
|
||||||
if (firstDataRowNum <= usedRowNum)
|
if (firstDataRowNum <= usedRowNum)
|
||||||
{
|
{
|
||||||
var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title.RootTitle, (sheet.Range[$"A{firstDataRowNum}:A{usedRowNum}"]).EntireRow);
|
var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, (sheet.Range[$"A{firstDataRowNum}:A{usedRowNum}"]).EntireRow);
|
||||||
ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords);
|
ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords);
|
||||||
CleanRemovedRecordFiles(LastLoadTableData, newRecords);
|
CleanRemovedRecordFiles(LastLoadTableData, newRecords);
|
||||||
}
|
}
|
||||||
|
|
@ -241,12 +241,12 @@ namespace LubanAssistant
|
||||||
MessageBox.Show("没有选中的行");
|
MessageBox.Show("没有选中的行");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SaveRecords((Worksheet sheet, Dictionary<string, string> metaAttrs, TableDataInfo tableDataInfo, DefTable defTable, TitleInfo title) =>
|
SaveRecords((Worksheet sheet, int titleRowNum, TableDataInfo tableDataInfo, DefTable defTable, Title title) =>
|
||||||
{
|
{
|
||||||
int usedRowNum = sheet.UsedRange.Rows.Count;
|
int usedRowNum = sheet.UsedRange.Rows.Count;
|
||||||
if (title.RowNum + 1 < usedRowNum)
|
if (titleRowNum + 1 < usedRowNum)
|
||||||
{
|
{
|
||||||
var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title.RootTitle, selectRange.EntireRow);
|
var newRecords = ExcelUtil.LoadRecordsInRange(defTable, sheet, title, selectRange.EntireRow);
|
||||||
ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords);
|
ExcelUtil.SaveRecords(InputDataDir, defTable, newRecords);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -17,51 +17,81 @@ namespace LubanAssistant
|
||||||
{
|
{
|
||||||
static class ExcelUtil
|
static class ExcelUtil
|
||||||
{
|
{
|
||||||
public static Dictionary<string, string> ParseMetaAttrs(Worksheet sheet)
|
public static RawSheet ParseRawSheet(Worksheet sheet, Range toSaveRecordRows)
|
||||||
{
|
{
|
||||||
Range metaRow = sheet.Rows[1];
|
if (!ParseMetaAttrs(sheet, out var orientRow, out var titleRows, out var tableName))
|
||||||
if (metaRow.Cells[1, 1].Text.ToString() != "##")
|
|
||||||
{
|
{
|
||||||
throw new Exception("A1 should be ##");
|
throw new Exception($"meta行不合法");
|
||||||
}
|
}
|
||||||
var metaAttrs = new Dictionary<string, string>();
|
|
||||||
for (int i = 2, n = sheet.UsedRange.Columns.Count; i <= n; i++)
|
if (!orientRow)
|
||||||
{
|
{
|
||||||
Range cell = metaRow.Cells[1, i];
|
throw new Exception($"目前只支持行表");
|
||||||
string value = cell.Value?.ToString();
|
}
|
||||||
if (!string.IsNullOrWhiteSpace(value))
|
|
||||||
|
Title title = ParseTitles(sheet);
|
||||||
|
var cells = new List<List<Cell>>();
|
||||||
|
|
||||||
|
foreach (Range row in toSaveRecordRows)
|
||||||
|
{
|
||||||
|
var rowCell = new List<Cell>();
|
||||||
|
for (int i = title.FromIndex; i <= title.ToIndex; i++)
|
||||||
{
|
{
|
||||||
var attrs = value.Split('=');
|
rowCell.Add(new Cell(row.Row - 1, i, (row.Cells[1, i + 1] as Range).Value));
|
||||||
if (attrs.Length != 2)
|
|
||||||
{
|
|
||||||
throw new Exception($"invalid meta attr:{value}");
|
|
||||||
}
|
|
||||||
metaAttrs.Add(attrs[0], attrs[1]);
|
|
||||||
}
|
}
|
||||||
|
cells.Add(rowCell);
|
||||||
}
|
}
|
||||||
return metaAttrs;
|
return new RawSheet() { Title = title, TitleRowCount = titleRows, TableName = tableName, Cells = cells };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TitleInfo ParseTitles(Worksheet sheet)
|
public static RawSheet ParseRawSheetTitleOnly(Worksheet sheet)
|
||||||
{
|
{
|
||||||
|
if (!ParseMetaAttrs(sheet, out var orientRow, out var titleRows, out var tableName))
|
||||||
|
{
|
||||||
|
throw new Exception($"meta行不合法");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!orientRow)
|
||||||
|
{
|
||||||
|
throw new Exception($"目前只支持行表");
|
||||||
|
}
|
||||||
|
|
||||||
|
Title title = ParseTitles(sheet);
|
||||||
|
var cells = new List<List<Cell>>();
|
||||||
|
return new RawSheet() { Title = title, TitleRowCount = titleRows, TableName = tableName, Cells = cells };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ParseMetaAttrs(Worksheet sheet, out bool orientRow, out int titleRows, out string tableName)
|
||||||
|
{
|
||||||
|
Range metaRow = sheet.Rows[1];
|
||||||
|
|
||||||
|
var cells = new List<string>();
|
||||||
|
for (int i = 1, n = sheet.UsedRange.Columns.Count; i <= n; i++)
|
||||||
|
{
|
||||||
|
cells.Add(((Range)metaRow.Cells[1, i]).Value?.ToString());
|
||||||
|
}
|
||||||
|
return SheetLoadUtil.TryParseMeta(cells, out orientRow, out titleRows, out tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Title ParseTitles(Worksheet sheet)
|
||||||
|
{
|
||||||
int titleRows = 1;
|
int titleRows = 1;
|
||||||
Range c1 = sheet.Cells[2, 1];
|
Range c1 = sheet.Cells[2, 1];
|
||||||
if (c1.MergeCells)
|
if (c1.MergeCells)
|
||||||
{
|
{
|
||||||
titleRows = c1.MergeArea.Count;
|
titleRows = c1.MergeArea.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var rootTile = new Title()
|
var rootTile = new Title()
|
||||||
{
|
{
|
||||||
FromIndex = 2,
|
FromIndex = 0,
|
||||||
ToIndex = sheet.UsedRange.Columns.Count,
|
ToIndex = sheet.UsedRange.Columns.Count - 1,
|
||||||
Name = "__root__",
|
Name = "__root__",
|
||||||
Root = true,
|
Root = true,
|
||||||
|
Tags = new Dictionary<string, string>(),
|
||||||
};
|
};
|
||||||
ParseSubTitle(sheet, 2, titleRows + 1, rootTile);
|
ParseSubTitle(sheet, 2, titleRows + 1, rootTile);
|
||||||
return new TitleInfo(rootTile, titleRows);
|
rootTile.Init();
|
||||||
|
return rootTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParseSubTitle(Worksheet sheet, int rowIndex, int maxRowIndex, Title title)
|
private static void ParseSubTitle(Worksheet sheet, int rowIndex, int maxRowIndex, Title title)
|
||||||
|
|
@ -69,51 +99,23 @@ namespace LubanAssistant
|
||||||
Range row = sheet.Rows[rowIndex];
|
Range row = sheet.Rows[rowIndex];
|
||||||
for (int i = title.FromIndex; i <= title.ToIndex; i++)
|
for (int i = title.FromIndex; i <= title.ToIndex; i++)
|
||||||
{
|
{
|
||||||
Range subTitleRange = row.Cells[1, i];
|
Range subTitleRange = row.Cells[1, i + 1];
|
||||||
string subTitleValue = subTitleRange.Value?.ToString();
|
string subTitleValue = subTitleRange.Value?.ToString();
|
||||||
if (string.IsNullOrWhiteSpace(subTitleValue))
|
if (string.IsNullOrWhiteSpace(subTitleValue))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var attrs = subTitleValue.Split('&');
|
var (subTitleName, tags) = SheetLoadUtil.ParseNameAndMetaAttrs(subTitleValue);
|
||||||
string subTitleName = attrs[0];
|
|
||||||
string sep = "";
|
|
||||||
foreach (var attrPair in attrs.Skip(1))
|
|
||||||
{
|
|
||||||
var pairs = attrPair.Split('=');
|
|
||||||
if (pairs.Length != 2)
|
|
||||||
{
|
|
||||||
throw new Exception($"invalid title: {subTitleValue}");
|
|
||||||
}
|
|
||||||
switch (pairs[0])
|
|
||||||
{
|
|
||||||
case "sep":
|
|
||||||
{
|
|
||||||
sep = pairs[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new Exception($"invalid title: {subTitleValue}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title.SubTitles.ContainsKey(subTitleName))
|
|
||||||
{
|
|
||||||
throw new Exception($"title:{subTitleName} 重复");
|
|
||||||
}
|
|
||||||
var newSubTitle = new Title()
|
var newSubTitle = new Title()
|
||||||
{
|
{
|
||||||
Name = subTitleName,
|
Name = subTitleName,
|
||||||
FromIndex = i,
|
FromIndex = i,
|
||||||
ToIndex = i,
|
Tags = tags,
|
||||||
};
|
};
|
||||||
if (!string.IsNullOrWhiteSpace(sep))
|
|
||||||
{
|
|
||||||
newSubTitle.Sep = sep;
|
|
||||||
}
|
|
||||||
if (subTitleRange.MergeCells)
|
if (subTitleRange.MergeCells)
|
||||||
{
|
{
|
||||||
newSubTitle.ToIndex = i + subTitleRange.MergeArea.Count - 1;
|
newSubTitle.ToIndex = i + subTitleRange.MergeArea.Count - 1;
|
||||||
|
|
@ -122,9 +124,8 @@ namespace LubanAssistant
|
||||||
{
|
{
|
||||||
newSubTitle.ToIndex = i;
|
newSubTitle.ToIndex = i;
|
||||||
}
|
}
|
||||||
title.SubTitles.Add(subTitleName, newSubTitle);
|
title.AddSubTitle(newSubTitle);
|
||||||
}
|
}
|
||||||
title.SubTitleList.AddRange(title.SubTitles.Values);
|
|
||||||
if (rowIndex < maxRowIndex)
|
if (rowIndex < maxRowIndex)
|
||||||
{
|
{
|
||||||
foreach (var subTitle in title.SubTitleList)
|
foreach (var subTitle in title.SubTitleList)
|
||||||
|
|
@ -134,17 +135,8 @@ namespace LubanAssistant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FillRecords(Worksheet sheet, Dictionary<string, string> metaAttrs, TitleInfo title, TableDataInfo tableDataInfo)
|
public static void FillRecords(Worksheet sheet, int titleRowNum, Title title, TableDataInfo tableDataInfo)
|
||||||
{
|
{
|
||||||
int titleRowNum = 3;
|
|
||||||
if (metaAttrs.TryGetValue("title_rows", out var titleRowsStr) && !int.TryParse(titleRowsStr, out titleRowNum))
|
|
||||||
{
|
|
||||||
throw new Exception($"meta 属性 title_rows 不合法");
|
|
||||||
}
|
|
||||||
if (titleRowNum < title.RowNum)
|
|
||||||
{
|
|
||||||
throw new Exception($"meta 属性title_rows不能比字段名行的行数小");
|
|
||||||
}
|
|
||||||
int usedRowNum = sheet.UsedRange.Rows.Count;
|
int usedRowNum = sheet.UsedRange.Rows.Count;
|
||||||
if (usedRowNum > titleRowNum + 1)
|
if (usedRowNum > titleRowNum + 1)
|
||||||
{
|
{
|
||||||
|
|
@ -158,35 +150,17 @@ namespace LubanAssistant
|
||||||
{
|
{
|
||||||
var fillVisitor = new FillSheetVisitor(sheet, nextRowIndex);
|
var fillVisitor = new FillSheetVisitor(sheet, nextRowIndex);
|
||||||
//FillRecord(sheet, ref nextRowIndex, title.RootTitle, rec);
|
//FillRecord(sheet, ref nextRowIndex, title.RootTitle, rec);
|
||||||
nextRowIndex += rec.Data.Apply(fillVisitor, title.RootTitle);
|
nextRowIndex += rec.Data.Apply(fillVisitor, title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Record> LoadRecordsInRange(DefTable table, Worksheet sheet, Title title, Range toSaveRecordRows)
|
public static List<Record> LoadRecordsInRange(DefTable table, Worksheet sheet, Title title, Range toSaveRecordRows)
|
||||||
{
|
{
|
||||||
var recs = new List<Record>();
|
RawSheet rawSheet = ParseRawSheet(sheet, toSaveRecordRows);
|
||||||
foreach (Range row in toSaveRecordRows)
|
var excelSource = new ExcelDataSource();
|
||||||
{
|
excelSource.Load(rawSheet);
|
||||||
bool allEmpty = true;
|
|
||||||
for (int i = title.FromIndex; i <= title.ToIndex; i++)
|
return excelSource.ReadMulti(table.ValueTType);
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty((row.Cells[1, i] as Range).Value?.ToString()))
|
|
||||||
{
|
|
||||||
allEmpty = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allEmpty)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
string tags = (row.Cells[1, 1] as Range).Value?.ToString();
|
|
||||||
recs.Add(new Record(
|
|
||||||
(DBean)table.ValueTType.Apply(new SheetDataCreator(sheet, row.Row, table.Assembly), title, null),
|
|
||||||
"",
|
|
||||||
DataUtil.ParseTags(tags)));
|
|
||||||
}
|
|
||||||
return recs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveRecords(string inputDataDir, DefTable table, List<Record> records)
|
public static void SaveRecords(string inputDataDir, DefTable table, List<Record> records)
|
||||||
|
|
|
||||||
|
|
@ -26,75 +26,77 @@ namespace LubanAssistant
|
||||||
_startRowIndex = startRowIndex;
|
_startRowIndex = startRowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Range Current(Title title) => _cells[_startRowIndex, title.FromIndex + 1] as Range;
|
||||||
|
|
||||||
public int Accept(DBool type, Title x)
|
public int Accept(DBool type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DByte type, Title x)
|
public int Accept(DByte type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DShort type, Title x)
|
public int Accept(DShort type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DFshort type, Title x)
|
public int Accept(DFshort type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DInt type, Title x)
|
public int Accept(DInt type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DFint type, Title x)
|
public int Accept(DFint type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DLong type, Title x)
|
public int Accept(DLong type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DFlong type, Title x)
|
public int Accept(DFlong type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DFloat type, Title x)
|
public int Accept(DFloat type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DDouble type, Title x)
|
public int Accept(DDouble type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DEnum type, Title x)
|
public int Accept(DEnum type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.StrValue;
|
Current(x).Value = type.StrValue;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DString type, Title x)
|
public int Accept(DString type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Value;
|
Current(x).Value = type.Value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +111,7 @@ namespace LubanAssistant
|
||||||
//{
|
//{
|
||||||
// throw new Exception($"title:{x.Name}为text类型,至少要占两列");
|
// throw new Exception($"title:{x.Name}为text类型,至少要占两列");
|
||||||
//}
|
//}
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
//(_cells[_startRowIndex, x.FromIndex + 1] as Range).Value = type.RawValue;
|
//(_cells[_startRowIndex, x.FromIndex + 1] as Range).Value = type.RawValue;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -126,11 +128,11 @@ namespace LubanAssistant
|
||||||
}
|
}
|
||||||
if (type.ImplType != null)
|
if (type.ImplType != null)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, typeTitle.FromIndex] as Range).Value = type.ImplType.Name;
|
Current(typeTitle).Value = type.ImplType.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, typeTitle.FromIndex] as Range).Value = DefBean.BEAN_NULL_STR;
|
Current(typeTitle).Value = DefBean.BEAN_NULL_STR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -141,7 +143,7 @@ namespace LubanAssistant
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//(_cells[_startRowIndex, x.FromIndex] as Range).Value = "null";
|
//Current(x).Value = "null";
|
||||||
throw new Exception($"title:{x.Name} 不支持 值为null的普通bean");
|
throw new Exception($"title:{x.Name} 不支持 值为null的普通bean");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,59 +175,59 @@ namespace LubanAssistant
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DArray type, Title x)
|
public int Accept(DArray type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DList type, Title x)
|
public int Accept(DList type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DSet type, Title x)
|
public int Accept(DSet type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DMap type, Title x)
|
public int Accept(DMap type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
Current(x).Value = type.Apply(ToExcelStringVisitor.Ins, x.Sep);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DVector2 type, Title x)
|
public int Accept(DVector2 type, Title x)
|
||||||
{
|
{
|
||||||
var v = type.Value;
|
var v = type.Value;
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y}";
|
Current(x).Value = $"{v.X},{v.Y}";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DVector3 type, Title x)
|
public int Accept(DVector3 type, Title x)
|
||||||
{
|
{
|
||||||
var v = type.Value;
|
var v = type.Value;
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y},{v.Z}";
|
Current(x).Value = $"{v.X},{v.Y},{v.Z}";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DVector4 type, Title x)
|
public int Accept(DVector4 type, Title x)
|
||||||
{
|
{
|
||||||
var v = type.Value;
|
var v = type.Value;
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = $"{v.X},{v.Y},{v.Z},{v.W}";
|
Current(x).Value = $"{v.X},{v.Y},{v.Z},{v.W}";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Accept(DDateTime type, Title x)
|
public int Accept(DDateTime type, Title x)
|
||||||
{
|
{
|
||||||
(_cells[_startRowIndex, x.FromIndex] as Range).Value = type.Time;
|
Current(x).Value = type.Time;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,11 +229,8 @@
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\DataCreateException.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\DataCreateException.cs">
|
||||||
<Link>Source\DataCreators\DataCreateException.cs</Link>
|
<Link>Source\DataCreators\DataCreateException.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\ExcelDataCreator.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\ExcelStreamDataCreator.cs">
|
||||||
<Link>Source\DataCreators\ExcelDataCreator.cs</Link>
|
<Link>Source\DataCreators\ExcelStreamDataCreator.cs</Link>
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\ExcelNamedRowDataCreator.cs">
|
|
||||||
<Link>Source\DataCreators\ExcelNamedRowDataCreator.cs</Link>
|
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\JsonDataCreator.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\JsonDataCreator.cs">
|
||||||
<Link>Source\DataCreators\JsonDataCreator.cs</Link>
|
<Link>Source\DataCreators\JsonDataCreator.cs</Link>
|
||||||
|
|
@ -244,6 +241,9 @@
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\MultiRowExcelDataCreator.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\MultiRowExcelDataCreator.cs">
|
||||||
<Link>Source\DataCreators\MultiRowExcelDataCreator.cs</Link>
|
<Link>Source\DataCreators\MultiRowExcelDataCreator.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\SheetDataCreator.cs">
|
||||||
|
<Link>Source\DataCreators\SheetDataCreator.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\StringDataCreator.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\StringDataCreator.cs">
|
||||||
<Link>Source\DataCreators\StringDataCreator.cs</Link>
|
<Link>Source\DataCreators\StringDataCreator.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -271,12 +271,24 @@
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\ExcelStream.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\ExcelStream.cs">
|
||||||
<Link>Source\DataSources\Excel\ExcelStream.cs</Link>
|
<Link>Source\DataSources\Excel\ExcelStream.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\RawSheet.cs">
|
||||||
|
<Link>Source\DataSources\Excel\RawSheet.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\RawSheetTableDefInfo.cs">
|
||||||
|
<Link>Source\DataCreators\RawSheetTableDefInfo.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\Sheet.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\Sheet.cs">
|
||||||
<Link>Source\DataSources\Excel\Sheet.cs</Link>
|
<Link>Source\DataSources\Excel\Sheet.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\SheetLoadUtil.cs">
|
||||||
|
<Link>Source\DataSources\Excel\SheetLoadUtil.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\Title.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\Title.cs">
|
||||||
<Link>Source\DataSources\Excel\Title.cs</Link>
|
<Link>Source\DataSources\Excel\Title.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\TitleRow.cs">
|
||||||
|
<Link>Source\DataSources\Excel\TitleRow.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Json\JsonDataSource.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Json\JsonDataSource.cs">
|
||||||
<Link>Source\DataSources\Json\JsonDataSource.cs</Link>
|
<Link>Source\DataSources\Json\JsonDataSource.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -364,18 +376,33 @@
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\IDataFuncVisitor.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\IDataFuncVisitor.cs">
|
||||||
<Link>Source\DataVisitors\IDataFuncVisitor.cs</Link>
|
<Link>Source\DataVisitors\IDataFuncVisitor.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\IsDefaultValue.cs">
|
||||||
|
<Link>Source\DataVisitors\IsDefaultValue.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\ToLiteralVisitorBase.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\ToLiteralVisitorBase.cs">
|
||||||
<Link>Source\DataVisitors\ToLiteralVisitorBase.cs</Link>
|
<Link>Source\DataVisitors\ToLiteralVisitorBase.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\ToStringVisitor.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\ToStringVisitor.cs">
|
||||||
<Link>Source\DataVisitors\ToStringVisitor.cs</Link>
|
<Link>Source\DataVisitors\ToStringVisitor.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\ValidatorVisitor.cs">
|
||||||
|
<Link>Source\DataVisitors\ValidatorVisitor.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\CfgDefLoader.cs">
|
||||||
|
<Link>Source\Defs\CfgDefLoader.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\CfgDefTypeBase.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\CfgDefTypeBase.cs">
|
||||||
<Link>Source\Defs\CfgDefTypeBase.cs</Link>
|
<Link>Source\Defs\CfgDefTypeBase.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefAssembly.cs">
|
||||||
|
<Link>Source\Defs\DefAssembly.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefBean.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefBean.cs">
|
||||||
<Link>Source\Defs\DefBean.cs</Link>
|
<Link>Source\Defs\DefBean.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefField.cs">
|
||||||
|
<Link>Source\Defs\DefField.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefTable.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefTable.cs">
|
||||||
<Link>Source\Defs\DefTable.cs</Link>
|
<Link>Source\Defs\DefTable.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -418,6 +445,24 @@
|
||||||
<Compile Include="..\Luban.Job.Cfg\Source\Utils\DataUtil.cs">
|
<Compile Include="..\Luban.Job.Cfg\Source\Utils\DataUtil.cs">
|
||||||
<Link>Source\Utils\DataUtil.cs</Link>
|
<Link>Source\Utils\DataUtil.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\ValidatorContext.cs">
|
||||||
|
<Link>Source\ValidatorContext.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Validators\IValidator.cs">
|
||||||
|
<Link>Source\Validators\IValidator.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Validators\PathValidator.cs">
|
||||||
|
<Link>Source\Validators\PathValidator.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Validators\RangeValidator.cs">
|
||||||
|
<Link>Source\Validators\RangeValidator.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Validators\RefValidator.cs">
|
||||||
|
<Link>Source\Validators\RefValidator.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Cfg\Source\Validators\ValidatorFactory.cs">
|
||||||
|
<Link>Source\Validators\ValidatorFactory.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Common\Source\Defs\CommonDefLoader.cs">
|
<Compile Include="..\Luban.Job.Common\Source\Defs\CommonDefLoader.cs">
|
||||||
<Link>Source\Defs\CommonDefLoader.cs</Link>
|
<Link>Source\Defs\CommonDefLoader.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -433,6 +478,9 @@
|
||||||
<Compile Include="..\Luban.Job.Common\Source\Defs\DefFieldBase.cs">
|
<Compile Include="..\Luban.Job.Common\Source\Defs\DefFieldBase.cs">
|
||||||
<Link>Source\Defs\DefFieldBase.cs</Link>
|
<Link>Source\Defs\DefFieldBase.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Luban.Job.Common\Source\Defs\DefTypeBase.cs">
|
||||||
|
<Link>Source\Defs\DefTypeBase.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Luban.Job.Common\Source\ELanguage.cs">
|
<Compile Include="..\Luban.Job.Common\Source\ELanguage.cs">
|
||||||
<Link>Source\ELanguage.cs</Link>
|
<Link>Source\ELanguage.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -550,7 +598,6 @@
|
||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="SheetDataCreator.cs" />
|
|
||||||
<Compile Include="Source\DataExporters\RawJsonExportor.cs" />
|
<Compile Include="Source\DataExporters\RawJsonExportor.cs" />
|
||||||
<Compile Include="ToExcelStringVisitor.cs" />
|
<Compile Include="ToExcelStringVisitor.cs" />
|
||||||
<EmbeddedResource Include="AssistantTab.resx">
|
<EmbeddedResource Include="AssistantTab.resx">
|
||||||
|
|
@ -577,7 +624,6 @@
|
||||||
<DependentUpon>Settings.settings</DependentUpon>
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Source\DataSources\Excel\TitleInfo.cs" />
|
|
||||||
<Compile Include="Source\Utils\AtomicLong.cs" />
|
<Compile Include="Source\Utils\AtomicLong.cs" />
|
||||||
<Compile Include="Source\Utils\CacheFileUtil.cs" />
|
<Compile Include="Source\Utils\CacheFileUtil.cs" />
|
||||||
<Compile Include="Source\Collections\CollectionExtension.cs" />
|
<Compile Include="Source\Collections\CollectionExtension.cs" />
|
||||||
|
|
@ -590,10 +636,6 @@
|
||||||
<Compile Include="Source\Common\ValueUtil.cs" />
|
<Compile Include="Source\Common\ValueUtil.cs" />
|
||||||
<Compile Include="Source\Datas\DText.cs" />
|
<Compile Include="Source\Datas\DText.cs" />
|
||||||
<Compile Include="Source\Datas\DType.cs" />
|
<Compile Include="Source\Datas\DType.cs" />
|
||||||
<Compile Include="Source\Defs\CfgDefLoader.cs" />
|
|
||||||
<Compile Include="Source\Defs\DefAssembly.cs" />
|
|
||||||
<Compile Include="Source\Defs\DefField.cs" />
|
|
||||||
<Compile Include="Source\Defs\DefTypeBase.cs" />
|
|
||||||
<Compile Include="Source\Protos\FileInfo.cs" />
|
<Compile Include="Source\Protos\FileInfo.cs" />
|
||||||
<Compile Include="Source\Protos\GetImportFileOrDirectory.cs" />
|
<Compile Include="Source\Protos\GetImportFileOrDirectory.cs" />
|
||||||
<Compile Include="Source\LocalAgent.cs" />
|
<Compile Include="Source\LocalAgent.cs" />
|
||||||
|
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
using Luban.Common.Utils;
|
|
||||||
using Luban.Job.Cfg.DataCreators;
|
|
||||||
using Luban.Job.Cfg.Datas;
|
|
||||||
using Luban.Job.Cfg.DataSources.Excel;
|
|
||||||
using Luban.Job.Cfg.Defs;
|
|
||||||
using Luban.Job.Common.Types;
|
|
||||||
using Luban.Job.Common.TypeVisitors;
|
|
||||||
using Microsoft.Office.Interop.Excel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace LubanAssistant
|
|
||||||
{
|
|
||||||
class SheetDataCreator : ITypeFuncVisitor<Title, DefField, DType>
|
|
||||||
{
|
|
||||||
private readonly Worksheet _sheet;
|
|
||||||
private readonly int _rowIndex;
|
|
||||||
private readonly DefAssembly _defAss;
|
|
||||||
|
|
||||||
public SheetDataCreator(Worksheet sheet, int rowIndex, DefAssembly ass)
|
|
||||||
{
|
|
||||||
_sheet = sheet;
|
|
||||||
_rowIndex = rowIndex;
|
|
||||||
_defAss = ass;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private ExcelStream CreateStream(Title title, bool nameMode = true)
|
|
||||||
{
|
|
||||||
return new ExcelStream(new Cell(title.FromIndex, title.ToIndex, _sheet.Cells[_rowIndex, title.FromIndex].Value), title.Sep, nameMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TBool type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TByte type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TShort type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TFshort type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TInt type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TFint type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TLong type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TFlong type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TFloat type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TDouble type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TEnum type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TString type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TBytes type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TText type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TBean type, Title title, DefField defField)
|
|
||||||
{
|
|
||||||
if (title.HasSubTitle)
|
|
||||||
{
|
|
||||||
var originBean = (DefBean)type.Bean;
|
|
||||||
DefBean implType;
|
|
||||||
if (originBean.IsAbstractType)
|
|
||||||
{
|
|
||||||
if (!title.SubTitles.TryGetValue(DefBean.TYPE_NAME_KEY, out var typeTitle))
|
|
||||||
{
|
|
||||||
throw new Exception($"title:{title.Name} 缺失 子title:{DefBean.TYPE_NAME_KEY}");
|
|
||||||
}
|
|
||||||
|
|
||||||
string subType = (_sheet.Cells[_rowIndex, typeTitle.FromIndex] as Range).Value.ToString().Trim();
|
|
||||||
if (subType.ToLower() == DefBean.BEAN_NULL_STR)
|
|
||||||
{
|
|
||||||
if (!type.IsNullable)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{type}' 不是可空类型 '{type.Bean.FullName}?' , 不能为空");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
string fullType = TypeUtil.MakeFullName(originBean.Namespace, subType);
|
|
||||||
implType = (DefBean)originBean.GetNotAbstractChildType(subType);
|
|
||||||
if (implType == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{fullType}' 不是 bean 类型");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
implType = originBean;
|
|
||||||
}
|
|
||||||
var fields = new List<DType>();
|
|
||||||
foreach (var f in implType.HierarchyFields)
|
|
||||||
{
|
|
||||||
if (!title.SubTitles.TryGetValue(f.Name, out var subTitle))
|
|
||||||
{
|
|
||||||
throw new Exception($"title:{title.Name} 缺失子title:{f.Name}");
|
|
||||||
}
|
|
||||||
fields.Add(f.CType.Apply(this, subTitle, (DefField)f));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DBean(originBean, implType, fields);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, defField, CreateStream(title, false), _defAss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TArray type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TList type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TSet type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TMap type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TVector2 type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TVector3 type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TVector4 type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DType Accept(TDateTime type, Title x, DefField y)
|
|
||||||
{
|
|
||||||
return type.Apply(ExcelDataCreator.Ins, y, CreateStream(x), _defAss);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Luban.Job.Cfg.DataSources.Excel
|
|
||||||
{
|
|
||||||
class TitleInfo
|
|
||||||
{
|
|
||||||
public Title RootTitle { get; }
|
|
||||||
|
|
||||||
public int RowNum { get; }
|
|
||||||
|
|
||||||
public TitleInfo(Title rootTitle, int rowNum)
|
|
||||||
{
|
|
||||||
RootTitle = rootTitle;
|
|
||||||
RowNum = rowNum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,893 +0,0 @@
|
||||||
using Bright.Collections;
|
|
||||||
using Luban.Common.Utils;
|
|
||||||
using Luban.Job.Cfg.Datas;
|
|
||||||
using Luban.Job.Cfg.DataSources.Excel;
|
|
||||||
using Luban.Job.Cfg.RawDefs;
|
|
||||||
using Luban.Job.Cfg.Utils;
|
|
||||||
using Luban.Job.Common.Defs;
|
|
||||||
using Luban.Job.Common.RawDefs;
|
|
||||||
using Luban.Job.Common.Types;
|
|
||||||
using Luban.Job.Common.Utils;
|
|
||||||
using Luban.Server.Common;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Luban.Job.Cfg.Defs
|
|
||||||
{
|
|
||||||
public class CfgDefLoader : CommonDefLoader
|
|
||||||
{
|
|
||||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
private readonly List<string> _importExcelTableFiles = new();
|
|
||||||
private readonly List<string> _importExcelEnumFiles = new();
|
|
||||||
private readonly List<string> _importExcelBeanFiles = new();
|
|
||||||
|
|
||||||
|
|
||||||
private readonly List<Patch> _patches = new();
|
|
||||||
|
|
||||||
private readonly List<Table> _cfgTables = new List<Table>();
|
|
||||||
|
|
||||||
private readonly List<Service> _cfgServices = new List<Service>();
|
|
||||||
|
|
||||||
private readonly List<Group> _cfgGroups = new List<Group>();
|
|
||||||
|
|
||||||
private readonly List<string> _defaultGroups = new List<string>();
|
|
||||||
|
|
||||||
public CfgDefLoader(IAgent agent) : base(agent)
|
|
||||||
{
|
|
||||||
RegisterRootDefineHandler("importexcel", AddImportExcel);
|
|
||||||
RegisterRootDefineHandler("patch", AddPatch);
|
|
||||||
RegisterRootDefineHandler("service", AddService);
|
|
||||||
RegisterRootDefineHandler("group", AddGroup);
|
|
||||||
|
|
||||||
RegisterModuleDefineHandler("table", AddTable);
|
|
||||||
|
|
||||||
|
|
||||||
IsBeanFieldMustDefineId = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Defines BuildDefines()
|
|
||||||
{
|
|
||||||
return new Defines()
|
|
||||||
{
|
|
||||||
TopModule = TopModule,
|
|
||||||
Patches = _patches,
|
|
||||||
Enums = _enums,
|
|
||||||
Beans = _beans,
|
|
||||||
Tables = _cfgTables,
|
|
||||||
Services = _cfgServices,
|
|
||||||
Groups = _cfgGroups,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> _excelImportRequireAttrs = new List<string> { "name", "type" };
|
|
||||||
private void AddImportExcel(XElement e)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(RootXml, e, null, _excelImportRequireAttrs);
|
|
||||||
var importName = XmlUtil.GetRequiredAttribute(e, "name");
|
|
||||||
if (string.IsNullOrWhiteSpace(importName))
|
|
||||||
{
|
|
||||||
throw new Exception("importexcel 属性name不能为空");
|
|
||||||
}
|
|
||||||
var type = XmlUtil.GetRequiredAttribute(e, "type");
|
|
||||||
if (string.IsNullOrWhiteSpace(type))
|
|
||||||
{
|
|
||||||
throw new Exception($"importexcel name:'{importName}' type属性不能为空");
|
|
||||||
}
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case "table": this._importExcelTableFiles.Add(importName); break;
|
|
||||||
case "enum": this._importExcelEnumFiles.Add(importName); break;
|
|
||||||
case "bean": this._importExcelBeanFiles.Add(importName); break;
|
|
||||||
default: throw new Exception($"importexcel name:'{importName}' type:'{type}' 不合法. 有效值为 table|enum|bean");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> _patchRequireAttrs = new List<string> { "name" };
|
|
||||||
private void AddPatch(XElement e)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(RootXml, e, null, _patchRequireAttrs);
|
|
||||||
var patchName = e.Attribute("name").Value;
|
|
||||||
if (string.IsNullOrWhiteSpace(patchName))
|
|
||||||
{
|
|
||||||
throw new Exception("patch 属性name不能为空");
|
|
||||||
}
|
|
||||||
if (this._patches.Any(b => b.Name == patchName))
|
|
||||||
{
|
|
||||||
throw new Exception($"patch '{patchName}' 重复");
|
|
||||||
}
|
|
||||||
_patches.Add(new Patch(patchName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> _groupOptionalAttrs = new List<string> { "default" };
|
|
||||||
private static readonly List<string> _groupRequireAttrs = new List<string> { "name" };
|
|
||||||
|
|
||||||
private void AddGroup(XElement e)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(RootXml, e, _groupOptionalAttrs, _groupRequireAttrs);
|
|
||||||
List<string> groupNames = CreateGroups(e.Attribute("name").Value);
|
|
||||||
|
|
||||||
foreach (var g in groupNames)
|
|
||||||
{
|
|
||||||
if (_cfgGroups.Any(cg => cg.Names.Contains(g)))
|
|
||||||
{
|
|
||||||
throw new Exception($"group名:'{g}' 重复");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XmlUtil.GetOptionBoolAttribute(e, "default"))
|
|
||||||
{
|
|
||||||
this._defaultGroups.AddRange(groupNames);
|
|
||||||
}
|
|
||||||
_cfgGroups.Add(new Group() { Names = groupNames });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillValueValidator(CfgField f, string attrValue, string validatorName)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(attrValue))
|
|
||||||
{
|
|
||||||
var validator = new Validator() { Type = validatorName, Rule = attrValue };
|
|
||||||
f.Validators.Add(validator);
|
|
||||||
f.ValueValidators.Add(validator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillValidators(string defineFile, string key, string attr, List<Validator> result)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(attr))
|
|
||||||
{
|
|
||||||
#if !LUBAN_LITE
|
|
||||||
foreach (var validatorStr in attr.Split('#', StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
#else
|
|
||||||
foreach (var validatorStr in attr.Split('#'))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
var sepIndex = validatorStr.IndexOf(':');
|
|
||||||
if (sepIndex <= 0)
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defineFile} key:'{key}' attr:'{attr}' 不是合法的 validator 定义 (key1:value1#key2:value2 ...)");
|
|
||||||
}
|
|
||||||
#if !LUBAN_LITE
|
|
||||||
result.Add(new Validator() { Type = validatorStr[..sepIndex], Rule = validatorStr[(sepIndex + 1)..] });
|
|
||||||
#else
|
|
||||||
result.Add(new Validator() { Type = validatorStr.Substring(0, sepIndex), Rule = validatorStr.Substring(sepIndex + 1, validatorStr.Length - sepIndex - 1) });
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<string> _serviceAttrs = new List<string> { "name", "manager", "group" };
|
|
||||||
|
|
||||||
private void AddService(XElement e)
|
|
||||||
{
|
|
||||||
var name = XmlUtil.GetRequiredAttribute(e, "name");
|
|
||||||
var manager = XmlUtil.GetRequiredAttribute(e, "manager");
|
|
||||||
List<string> groups = CreateGroups(XmlUtil.GetOptionalAttribute(e, "group"));
|
|
||||||
var refs = new List<string>();
|
|
||||||
|
|
||||||
s_logger.Trace("service name:{name} manager:{manager}", name, manager);
|
|
||||||
ValidAttrKeys(RootXml, e, _serviceAttrs, _serviceAttrs);
|
|
||||||
foreach (XElement ele in e.Elements())
|
|
||||||
{
|
|
||||||
string tagName = ele.Name.LocalName;
|
|
||||||
s_logger.Trace("service {service_name} tag: {name} {value}", name, tagName, ele);
|
|
||||||
switch (tagName)
|
|
||||||
{
|
|
||||||
case "ref":
|
|
||||||
{
|
|
||||||
refs.Add(XmlUtil.GetRequiredAttribute(ele, "name"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new Exception($"service:'{name}' tag:'{tagName}' 非法");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ValidGroup(groups, out var invalidGroup))
|
|
||||||
{
|
|
||||||
throw new Exception($"service:'{name}' group:'{invalidGroup}' 不存在");
|
|
||||||
}
|
|
||||||
_cfgServices.Add(new Service() { Name = name, Manager = manager, Groups = groups, Refs = refs });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private readonly Dictionary<string, Table> _name2CfgTable = new Dictionary<string, Table>();
|
|
||||||
|
|
||||||
private static List<string> CreateGroups(string s)
|
|
||||||
{
|
|
||||||
return s.Split(',', ';').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidGroup(List<string> groups, out string invalidGroup)
|
|
||||||
{
|
|
||||||
foreach (var g in groups)
|
|
||||||
{
|
|
||||||
if (!this._cfgGroups.Any(cg => cg.Names.Contains(g)))
|
|
||||||
{
|
|
||||||
invalidGroup = g;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
invalidGroup = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ETableMode ConvertMode(string defineFile, string tableName, string modeStr, string indexStr)
|
|
||||||
{
|
|
||||||
ETableMode mode;
|
|
||||||
switch (modeStr)
|
|
||||||
{
|
|
||||||
case "one":
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(indexStr))
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defineFile} table:'{tableName}' mode=one 是单例表,不支持定义index属性");
|
|
||||||
}
|
|
||||||
mode = ETableMode.ONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "map":
|
|
||||||
{
|
|
||||||
//if ((string.IsNullOrWhiteSpace(indexStr) || indexStr.Split(',').Length != 1))
|
|
||||||
//{
|
|
||||||
// throw new Exception($"定义文件:{CurImportFile} table:{tableName} 是单键表,必须在index属性里指定1个key");
|
|
||||||
//}
|
|
||||||
mode = ETableMode.MAP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "":
|
|
||||||
{
|
|
||||||
mode = ETableMode.MAP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"不支持的 mode:{modeStr}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<string> _tableOptionalAttrs = new List<string> { "index", "mode", "group", "patch_input", "comment", "define_from_file" };
|
|
||||||
private readonly List<string> _tableRequireAttrs = new List<string> { "name", "value", "input" };
|
|
||||||
|
|
||||||
private void AddTable(string defineFile, XElement e)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(defineFile, e, _tableOptionalAttrs, _tableRequireAttrs);
|
|
||||||
string name = XmlUtil.GetRequiredAttribute(e, "name");
|
|
||||||
string module = CurNamespace;
|
|
||||||
string valueType = XmlUtil.GetRequiredAttribute(e, "value");
|
|
||||||
bool defineFromFile = XmlUtil.GetOptionBoolAttribute(e, "define_from_file");
|
|
||||||
string index = XmlUtil.GetOptionalAttribute(e, "index");
|
|
||||||
string group = XmlUtil.GetOptionalAttribute(e, "group");
|
|
||||||
string comment = XmlUtil.GetOptionalAttribute(e, "comment");
|
|
||||||
string input = XmlUtil.GetRequiredAttribute(e, "input");
|
|
||||||
string patchInput = XmlUtil.GetOptionalAttribute(e, "patch_input");
|
|
||||||
string mode = XmlUtil.GetOptionalAttribute(e, "mode");
|
|
||||||
string tags = XmlUtil.GetOptionalAttribute(e, "tags");
|
|
||||||
AddTable(defineFile, name, module, valueType, index, mode, group, comment, defineFromFile, input, patchInput, tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddTable(string defineFile, string name, string module, string valueType, string index, string mode, string group,
|
|
||||||
string comment, bool defineFromExcel, string input, string patchInput, string tags)
|
|
||||||
{
|
|
||||||
var p = new Table()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Namespace = module,
|
|
||||||
ValueType = valueType,
|
|
||||||
LoadDefineFromFile = defineFromExcel,
|
|
||||||
Index = index,
|
|
||||||
Groups = CreateGroups(group),
|
|
||||||
Comment = comment,
|
|
||||||
Mode = ConvertMode(defineFile, name, mode, index),
|
|
||||||
Tags = tags,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (p.Groups.Count == 0)
|
|
||||||
{
|
|
||||||
p.Groups = this._defaultGroups;
|
|
||||||
}
|
|
||||||
else if (!ValidGroup(p.Groups, out var invalidGroup))
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' group:'{invalidGroup}' 不存在");
|
|
||||||
}
|
|
||||||
p.InputFiles.AddRange(input.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)));
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(patchInput))
|
|
||||||
{
|
|
||||||
foreach (var subPatchStr in patchInput.Split('|').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)))
|
|
||||||
{
|
|
||||||
var nameAndDirs = subPatchStr.Split(':');
|
|
||||||
if (nameAndDirs.Length != 2)
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 定义不合法");
|
|
||||||
}
|
|
||||||
var patchDirs = nameAndDirs[1].Split(',', ';').ToList();
|
|
||||||
if (!p.PatchInputFiles.TryAdd(nameAndDirs[0], patchDirs))
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 子patch:'{nameAndDirs[0]}' 重复");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_cfgTables.Add(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<CfgBean> LoadTableValueTypeDefineFromFileAsync(Table table, string dataDir)
|
|
||||||
{
|
|
||||||
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, table.InputFiles, dataDir);
|
|
||||||
var file = inputFileInfos[0];
|
|
||||||
var source = new ExcelDataSource();
|
|
||||||
var stream = new MemoryStream(await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5));
|
|
||||||
var sheet = source.LoadFirstSheet(file.OriginFile, file.SheetName, stream);
|
|
||||||
|
|
||||||
var cb = new CfgBean() { Namespace = table.Namespace, Name = table.ValueType, };
|
|
||||||
|
|
||||||
var rc = sheet.RowColumns;
|
|
||||||
var attrRow = sheet.RowColumns[0];
|
|
||||||
if (rc.Count < sheet.AttrRowCount + 1)
|
|
||||||
{
|
|
||||||
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} 至少包含 属性行和标题行");
|
|
||||||
}
|
|
||||||
var titleRow = sheet.RowColumns[sheet.AttrRowCount];
|
|
||||||
// 有可能没有注释行,此时使用标题行,这个是必须有的
|
|
||||||
var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow;
|
|
||||||
foreach (var f in sheet.RootFields)
|
|
||||||
{
|
|
||||||
var cf = new CfgField() { Name = f.Name, Id = 0 };
|
|
||||||
|
|
||||||
string[] attrs = (attrRow[f.FromIndex].Value?.ToString() ?? "").Trim().Split('&').Select(s => s.Trim()).ToArray();
|
|
||||||
|
|
||||||
if (attrs.Length == 0 || string.IsNullOrWhiteSpace(attrs[0]))
|
|
||||||
{
|
|
||||||
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' type missing!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优先取desc行,如果为空,则取title行
|
|
||||||
|
|
||||||
cf.Comment = descRow[f.FromIndex].Value?.ToString();
|
|
||||||
if (string.IsNullOrWhiteSpace(cf.Comment))
|
|
||||||
{
|
|
||||||
cf.Comment = titleRow[f.FromIndex].Value?.ToString();
|
|
||||||
}
|
|
||||||
if (string.IsNullOrWhiteSpace(cf.Comment))
|
|
||||||
{
|
|
||||||
cf.Comment = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
cf.Type = attrs[0];
|
|
||||||
|
|
||||||
for (int i = 1; i < attrs.Length; i++)
|
|
||||||
{
|
|
||||||
#if !LUBAN_LITE
|
|
||||||
var pair = attrs[i].Split('=', 2);
|
|
||||||
#else
|
|
||||||
var pair = attrs[i].Split(new char[] { '=' }, 2);
|
|
||||||
#endif
|
|
||||||
if (pair.Length != 2)
|
|
||||||
{
|
|
||||||
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!");
|
|
||||||
}
|
|
||||||
var attrName = pair[0].Trim();
|
|
||||||
var attrValue = pair[1].Trim();
|
|
||||||
switch (attrName)
|
|
||||||
{
|
|
||||||
case "index":
|
|
||||||
{
|
|
||||||
cf.Index = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "sep":
|
|
||||||
{
|
|
||||||
cf.Sep = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ref":
|
|
||||||
case "path":
|
|
||||||
case "range":
|
|
||||||
{
|
|
||||||
var validator = new Validator() { Type = attrName, Rule = attrValue };
|
|
||||||
cf.Validators.Add(validator);
|
|
||||||
cf.ValueValidators.Add(validator);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "multi_rows":
|
|
||||||
{
|
|
||||||
cf.IsMultiRow = attrValue == "1" || attrValue.Equals("true", StringComparison.OrdinalIgnoreCase);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "group":
|
|
||||||
{
|
|
||||||
cf.Groups = attrValue.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "comment":
|
|
||||||
{
|
|
||||||
cf.Comment = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "convert":
|
|
||||||
{
|
|
||||||
cf.Converter = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "default":
|
|
||||||
{
|
|
||||||
cf.DefaultValue = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "tags":
|
|
||||||
{
|
|
||||||
cf.Tags = attrValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "orientation":
|
|
||||||
{
|
|
||||||
cf.IsRowOrient = DefUtil.ParseOrientation(attrValue);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cb.Fields.Add(cf);
|
|
||||||
}
|
|
||||||
return cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadTableValueTypeDefinesFromFileAsync(string dataDir)
|
|
||||||
{
|
|
||||||
var loadTasks = new List<Task<CfgBean>>();
|
|
||||||
foreach (var table in this._cfgTables.Where(t => t.LoadDefineFromFile))
|
|
||||||
{
|
|
||||||
loadTasks.Add(Task.Run(async () => await this.LoadTableValueTypeDefineFromFileAsync(table, dataDir)));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var task in loadTasks)
|
|
||||||
{
|
|
||||||
this._beans.Add(await task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadTableListFromFileAsync(string dataDir)
|
|
||||||
{
|
|
||||||
if (this._importExcelTableFiles.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelTableFiles, dataDir);
|
|
||||||
|
|
||||||
var defTableRecordType = new DefBean(new CfgBean()
|
|
||||||
{
|
|
||||||
Namespace = "__intern__",
|
|
||||||
Name = "__TableRecord__",
|
|
||||||
Parent = "",
|
|
||||||
Alias = "",
|
|
||||||
IsValueType = false,
|
|
||||||
Sep = "",
|
|
||||||
TypeId = 0,
|
|
||||||
IsSerializeCompatible = false,
|
|
||||||
Fields = new List<Field>
|
|
||||||
{
|
|
||||||
new CfgField() { Name = "full_name", Type = "string" },
|
|
||||||
new CfgField() { Name = "value_type", Type = "string" },
|
|
||||||
new CfgField() { Name = "index", Type = "string" },
|
|
||||||
new CfgField() { Name = "mode", Type = "string" },
|
|
||||||
new CfgField() { Name = "group", Type = "string" },
|
|
||||||
new CfgField() { Name = "comment", Type = "string" },
|
|
||||||
new CfgField() { Name = "define_from_excel", Type = "bool" },
|
|
||||||
new CfgField() { Name = "input", Type = "string" },
|
|
||||||
new CfgField() { Name = "patch_input", Type = "string" },
|
|
||||||
new CfgField() { Name = "tags", Type = "string" },
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
AssemblyBase = new DefAssembly("", null, new List<string>(), Agent),
|
|
||||||
};
|
|
||||||
defTableRecordType.PreCompile();
|
|
||||||
defTableRecordType.Compile();
|
|
||||||
defTableRecordType.PostCompile();
|
|
||||||
var tableRecordType = TBean.Create(false, defTableRecordType);
|
|
||||||
|
|
||||||
foreach (var file in inputFileInfos)
|
|
||||||
{
|
|
||||||
var source = new ExcelDataSource();
|
|
||||||
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
|
|
||||||
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
|
|
||||||
foreach (var r in records)
|
|
||||||
{
|
|
||||||
DBean data = r.Data;
|
|
||||||
//s_logger.Info("== read text:{}", r.Data);
|
|
||||||
string fullName = (data.GetField("full_name") as DString).Value.Trim();
|
|
||||||
string name = TypeUtil.GetName(fullName);
|
|
||||||
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
throw new Exception($"file:{file.ActualFile} 定义了一个空的table类名");
|
|
||||||
}
|
|
||||||
string module = TypeUtil.GetNamespace(fullName);
|
|
||||||
string valueType = (data.GetField("value_type") as DString).Value.Trim();
|
|
||||||
string index = (data.GetField("index") as DString).Value.Trim();
|
|
||||||
string mode = (data.GetField("mode") as DString).Value.Trim();
|
|
||||||
string group = (data.GetField("group") as DString).Value.Trim();
|
|
||||||
string comment = (data.GetField("comment") as DString).Value.Trim();
|
|
||||||
bool isDefineFromExcel = (data.GetField("define_from_excel") as DBool).Value;
|
|
||||||
string inputFile = (data.GetField("input") as DString).Value.Trim();
|
|
||||||
string patchInput = (data.GetField("patch_input") as DString).Value.Trim();
|
|
||||||
string tags = (data.GetField("tags") as DString).Value.Trim();
|
|
||||||
AddTable(file.OriginFile, name, module, valueType, index, mode, group, comment, isDefineFromExcel, inputFile, patchInput, tags);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadEnumListFromFileAsync(string dataDir)
|
|
||||||
{
|
|
||||||
if (this._importExcelEnumFiles.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelEnumFiles, dataDir);
|
|
||||||
|
|
||||||
var defTableRecordType = new DefBean(new CfgBean()
|
|
||||||
{
|
|
||||||
Namespace = "__intern__",
|
|
||||||
Name = "__EnumInfo__",
|
|
||||||
Parent = "",
|
|
||||||
Alias = "",
|
|
||||||
IsValueType = false,
|
|
||||||
Sep = "",
|
|
||||||
TypeId = 0,
|
|
||||||
IsSerializeCompatible = false,
|
|
||||||
Fields = new List<Field>
|
|
||||||
{
|
|
||||||
new CfgField() { Name = "full_name", Type = "string" },
|
|
||||||
new CfgField() { Name = "item", Type = "string" },
|
|
||||||
new CfgField() { Name = "alias", Type = "string" },
|
|
||||||
new CfgField() { Name = "value", Type = "int" },
|
|
||||||
new CfgField() { Name = "comment", Type = "string" },
|
|
||||||
new CfgField() { Name = "tags", Type = "string" },
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
AssemblyBase = new DefAssembly("", null, new List<string>(), Agent),
|
|
||||||
};
|
|
||||||
defTableRecordType.PreCompile();
|
|
||||||
defTableRecordType.Compile();
|
|
||||||
defTableRecordType.PostCompile();
|
|
||||||
var tableRecordType = TBean.Create(false, defTableRecordType);
|
|
||||||
|
|
||||||
foreach (var file in inputFileInfos)
|
|
||||||
{
|
|
||||||
var source = new ExcelDataSource();
|
|
||||||
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
|
|
||||||
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
|
|
||||||
|
|
||||||
PEnum curEnum = null;
|
|
||||||
foreach (var r in records)
|
|
||||||
{
|
|
||||||
DBean data = r.Data;
|
|
||||||
//s_logger.Info("== read text:{}", r.Data);
|
|
||||||
string fullName = (data.GetField("full_name") as DString).Value.Trim();
|
|
||||||
string name = TypeUtil.GetName(fullName);
|
|
||||||
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
throw new Exception($"file:{file.ActualFile} 定义了一个空的enum类名");
|
|
||||||
}
|
|
||||||
string module = TypeUtil.GetNamespace(fullName);
|
|
||||||
|
|
||||||
if (curEnum == null || curEnum.Name != name || curEnum.Namespace != module)
|
|
||||||
{
|
|
||||||
curEnum = new PEnum() { Name = name, Namespace = module, IsFlags = false, Comment = "", IsUniqueItemId = true };
|
|
||||||
this._enums.Add(curEnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
string item = (data.GetField("item") as DString).Value.Trim();
|
|
||||||
if (string.IsNullOrWhiteSpace(item))
|
|
||||||
{
|
|
||||||
throw new Exception($"file:{file.ActualFile} module:'{module}' name:'{name}' 定义了一个空枚举项");
|
|
||||||
}
|
|
||||||
string alias = (data.GetField("alias") as DString).Value.Trim();
|
|
||||||
string value = (data.GetField("value") as DInt).Value.ToString();
|
|
||||||
string comment = (data.GetField("comment") as DString).Value.Trim();
|
|
||||||
string tags = (data.GetField("tags") as DString).Value.Trim();
|
|
||||||
curEnum.Items.Add(new EnumItem() { Name = item, Alias = alias, Value = value, Comment = comment, Tags = tags });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadBeanListFromFileAsync(string dataDir)
|
|
||||||
{
|
|
||||||
if (this._importExcelBeanFiles.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelBeanFiles, dataDir);
|
|
||||||
|
|
||||||
|
|
||||||
var ass = new DefAssembly("", null, new List<string>(), Agent);
|
|
||||||
|
|
||||||
var defBeanFieldType = new DefBean(new CfgBean()
|
|
||||||
{
|
|
||||||
Namespace = "__intern__",
|
|
||||||
Name = "__FieldInfo__",
|
|
||||||
Parent = "",
|
|
||||||
Alias = "",
|
|
||||||
IsValueType = false,
|
|
||||||
Sep = "",
|
|
||||||
TypeId = 0,
|
|
||||||
IsSerializeCompatible = false,
|
|
||||||
Fields = new List<Field>
|
|
||||||
{
|
|
||||||
new CfgField() { Name = "name", Type = "string" },
|
|
||||||
new CfgField() { Name = "type", Type = "string" },
|
|
||||||
new CfgField() { Name = "sep", Type = "string" },
|
|
||||||
new CfgField() { Name = "is_multi_rows", Type = "bool" },
|
|
||||||
new CfgField() { Name = "index", Type = "string" },
|
|
||||||
new CfgField() { Name = "group", Type = "string" },
|
|
||||||
new CfgField() { Name = "ref", Type = "string", IgnoreNameValidation = true },
|
|
||||||
new CfgField() { Name = "path", Type = "string" },
|
|
||||||
new CfgField() { Name = "comment", Type = "string" },
|
|
||||||
new CfgField() { Name = "tags", Type = "string" },
|
|
||||||
new CfgField() { Name = "orientation", Type = "string" },
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
AssemblyBase = ass,
|
|
||||||
};
|
|
||||||
|
|
||||||
defBeanFieldType.PreCompile();
|
|
||||||
defBeanFieldType.Compile();
|
|
||||||
defBeanFieldType.PostCompile();
|
|
||||||
|
|
||||||
ass.AddType(defBeanFieldType);
|
|
||||||
|
|
||||||
var defTableRecordType = new DefBean(new CfgBean()
|
|
||||||
{
|
|
||||||
Namespace = "__intern__",
|
|
||||||
Name = "__BeanInfo__",
|
|
||||||
Parent = "",
|
|
||||||
Alias = "",
|
|
||||||
IsValueType = false,
|
|
||||||
Sep = "",
|
|
||||||
TypeId = 0,
|
|
||||||
IsSerializeCompatible = false,
|
|
||||||
Fields = new List<Field>
|
|
||||||
{
|
|
||||||
new CfgField() { Name = "full_name", Type = "string" },
|
|
||||||
new CfgField() { Name = "sep", Type = "string" },
|
|
||||||
new CfgField() { Name = "comment", Type = "string" },
|
|
||||||
new CfgField() { Name = "tags", Type = "string" },
|
|
||||||
new CfgField() { Name = "fields", Type = "list,__FieldInfo__", IsMultiRow = true },
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
AssemblyBase = ass,
|
|
||||||
};
|
|
||||||
ass.AddType(defTableRecordType);
|
|
||||||
defTableRecordType.PreCompile();
|
|
||||||
defTableRecordType.Compile();
|
|
||||||
defTableRecordType.PostCompile();
|
|
||||||
ass.MarkMultiRows();
|
|
||||||
var tableRecordType = TBean.Create(false, defTableRecordType);
|
|
||||||
|
|
||||||
foreach (var file in inputFileInfos)
|
|
||||||
{
|
|
||||||
var source = new ExcelDataSource();
|
|
||||||
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
|
|
||||||
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
|
|
||||||
|
|
||||||
foreach (var r in records)
|
|
||||||
{
|
|
||||||
DBean data = r.Data;
|
|
||||||
//s_logger.Info("== read text:{}", r.Data);
|
|
||||||
string fullName = (data.GetField("full_name") as DString).Value.Trim();
|
|
||||||
string name = TypeUtil.GetName(fullName);
|
|
||||||
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
throw new Exception($"file:{file.ActualFile} 定义了一个空bean类名");
|
|
||||||
}
|
|
||||||
string module = TypeUtil.GetNamespace(fullName);
|
|
||||||
|
|
||||||
|
|
||||||
string sep = (data.GetField("sep") as DString).Value.Trim();
|
|
||||||
string comment = (data.GetField("comment") as DString).Value.Trim();
|
|
||||||
string tags = (data.GetField("tags") as DString).Value.Trim();
|
|
||||||
DList fields = data.GetField("fields") as DList;
|
|
||||||
var curBean = new CfgBean()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Namespace = module,
|
|
||||||
Sep = sep,
|
|
||||||
Comment = comment,
|
|
||||||
Tags = tags,
|
|
||||||
Parent = "",
|
|
||||||
Fields = fields.Datas.Select(d => (DBean)d).Select(b => this.CreateField(
|
|
||||||
file.ActualFile,
|
|
||||||
(b.GetField("name") as DString).Value.Trim(),
|
|
||||||
(b.GetField("type") as DString).Value.Trim(),
|
|
||||||
(b.GetField("index") as DString).Value.Trim(),
|
|
||||||
(b.GetField("sep") as DString).Value.Trim(),
|
|
||||||
(b.GetField("is_multi_rows") as DBool).Value,
|
|
||||||
(b.GetField("group") as DString).Value,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
(b.GetField("comment") as DString).Value.Trim(),
|
|
||||||
(b.GetField("ref") as DString).Value.Trim(),
|
|
||||||
(b.GetField("path") as DString).Value.Trim(),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
(b.GetField("tags") as DString).Value.Trim(),
|
|
||||||
false,
|
|
||||||
DefUtil.ParseOrientation((b.GetField("orientation") as DString).Value)
|
|
||||||
)).ToList(),
|
|
||||||
};
|
|
||||||
this._beans.Add(curBean);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadDefinesFromFileAsync(string dataDir)
|
|
||||||
{
|
|
||||||
await Task.WhenAll(LoadTableListFromFileAsync(dataDir), LoadEnumListFromFileAsync(dataDir), LoadBeanListFromFileAsync(dataDir));
|
|
||||||
await LoadTableValueTypeDefinesFromFileAsync(dataDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> _fieldOptionalAttrs = new()
|
|
||||||
{
|
|
||||||
"index",
|
|
||||||
"sep",
|
|
||||||
"validator",
|
|
||||||
"key_validator",
|
|
||||||
"value_validator",
|
|
||||||
"ref",
|
|
||||||
"path",
|
|
||||||
"range",
|
|
||||||
"multi_rows",
|
|
||||||
"group",
|
|
||||||
"res",
|
|
||||||
"convert",
|
|
||||||
"comment",
|
|
||||||
"tags",
|
|
||||||
"default",
|
|
||||||
"orientation",
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly List<string> _fieldRequireAttrs = new List<string> { "name", "type" };
|
|
||||||
|
|
||||||
protected override Field CreateField(string defineFile, XElement e)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(defineFile, e, _fieldOptionalAttrs, _fieldRequireAttrs);
|
|
||||||
|
|
||||||
return CreateField(defineFile, XmlUtil.GetRequiredAttribute(e, "name"),
|
|
||||||
XmlUtil.GetRequiredAttribute(e, "type"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "index"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "sep"),
|
|
||||||
XmlUtil.GetOptionBoolAttribute(e, "multi_rows"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "group"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "res"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "convert"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "comment"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "ref"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "path"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "range"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "key_validator"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "value_validator"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "validator"),
|
|
||||||
XmlUtil.GetOptionalAttribute(e, "tags"),
|
|
||||||
false,
|
|
||||||
DefUtil.ParseOrientation(XmlUtil.GetOptionalAttribute(e, "orientation"))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Field CreateField(string defileFile, string name, string type, string index, string sep, bool isMultiRow, string group, string resource, string converter,
|
|
||||||
string comment, string refs, string path, string range, string keyValidator, string valueValidator, string validator, string tags,
|
|
||||||
bool ignoreNameValidation, bool isRowOrient)
|
|
||||||
{
|
|
||||||
var f = new CfgField()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Index = index,
|
|
||||||
Sep = sep,
|
|
||||||
IsMultiRow = isMultiRow,
|
|
||||||
Groups = CreateGroups(group),
|
|
||||||
Resource = resource,
|
|
||||||
Converter = converter,
|
|
||||||
Comment = comment,
|
|
||||||
Tags = tags,
|
|
||||||
IgnoreNameValidation = ignoreNameValidation,
|
|
||||||
IsRowOrient = isRowOrient,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 字段与table的默认组不一样。
|
|
||||||
// table 默认只属于default=1的组
|
|
||||||
// 字段默认属于所有组
|
|
||||||
if (f.Groups.Count == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (!ValidGroup(f.Groups, out var invalidGroup))
|
|
||||||
{
|
|
||||||
throw new Exception($"定义文件:{defileFile} field:'{name}' group:'{invalidGroup}' 不存在");
|
|
||||||
}
|
|
||||||
f.Type = type;
|
|
||||||
|
|
||||||
|
|
||||||
FillValueValidator(f, refs, "ref");
|
|
||||||
FillValueValidator(f, path, "path"); // (ue4|unity|normal|regex);xxx;xxx
|
|
||||||
FillValueValidator(f, range, "range");
|
|
||||||
|
|
||||||
FillValidators(defileFile, "key_validator", keyValidator, f.KeyValidators);
|
|
||||||
FillValidators(defileFile, "value_validator", valueValidator, f.ValueValidators);
|
|
||||||
FillValidators(defileFile, "validator", validator, f.Validators);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> _beanOptinsAttrs = new List<string> { "value_type", "alias", "sep", "comment", "tags" };
|
|
||||||
private static readonly List<string> _beanRequireAttrs = new List<string> { "name" };
|
|
||||||
|
|
||||||
protected override void AddBean(string defineFile, XElement e, string parent)
|
|
||||||
{
|
|
||||||
ValidAttrKeys(defineFile, e, _beanOptinsAttrs, _beanRequireAttrs);
|
|
||||||
|
|
||||||
var b = new CfgBean()
|
|
||||||
{
|
|
||||||
Name = XmlUtil.GetRequiredAttribute(e, "name"),
|
|
||||||
Namespace = CurNamespace,
|
|
||||||
Parent = parent.Length > 0 ? parent : "",
|
|
||||||
TypeId = 0,
|
|
||||||
IsSerializeCompatible = true,
|
|
||||||
IsValueType = XmlUtil.GetOptionBoolAttribute(e, "value_type"),
|
|
||||||
Alias = XmlUtil.GetOptionalAttribute(e, "alias"),
|
|
||||||
Sep = XmlUtil.GetOptionalAttribute(e, "sep"),
|
|
||||||
Comment = XmlUtil.GetOptionalAttribute(e, "comment"),
|
|
||||||
Tags = XmlUtil.GetOptionalAttribute(e, "tags"),
|
|
||||||
};
|
|
||||||
var childBeans = new List<XElement>();
|
|
||||||
|
|
||||||
bool defineAnyChildBean = false;
|
|
||||||
foreach (XElement fe in e.Elements())
|
|
||||||
{
|
|
||||||
switch (fe.Name.LocalName)
|
|
||||||
{
|
|
||||||
case "var":
|
|
||||||
{
|
|
||||||
if (defineAnyChildBean)
|
|
||||||
{
|
|
||||||
throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 的多态子bean必须在所有成员字段 <var> 之前定义");
|
|
||||||
}
|
|
||||||
b.Fields.Add(CreateField(defineFile, fe)); ;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "bean":
|
|
||||||
{
|
|
||||||
defineAnyChildBean = true;
|
|
||||||
childBeans.Add(fe);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 不支持 tag:{fe.Name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s_logger.Trace("add bean:{@bean}", b);
|
|
||||||
_beans.Add(b);
|
|
||||||
|
|
||||||
var fullname = b.FullName;
|
|
||||||
foreach (var cb in childBeans)
|
|
||||||
{
|
|
||||||
AddBean(defineFile, cb, fullname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,276 +0,0 @@
|
||||||
using Bright.Collections;
|
|
||||||
using Luban.Job.Cfg.Datas;
|
|
||||||
using Luban.Job.Cfg.RawDefs;
|
|
||||||
using Luban.Job.Cfg.TypeVisitors;
|
|
||||||
using Luban.Job.Common.Defs;
|
|
||||||
using Luban.Server.Common;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Luban.Job.Cfg.Defs
|
|
||||||
{
|
|
||||||
public class TableDataInfo
|
|
||||||
{
|
|
||||||
public DefTable Table { get; }
|
|
||||||
|
|
||||||
public List<Record> MainRecords { get; }
|
|
||||||
|
|
||||||
public List<Record> PatchRecords { get; }
|
|
||||||
|
|
||||||
//public List<Record> FinalRecords { get; set; }
|
|
||||||
|
|
||||||
//public Dictionary<DType, Record> FinalRecordMap { get; set; }
|
|
||||||
|
|
||||||
public TableDataInfo(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
|
||||||
{
|
|
||||||
Table = table;
|
|
||||||
MainRecords = mainRecords;
|
|
||||||
PatchRecords = patchRecords;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DefAssembly : DefAssemblyBase
|
|
||||||
{
|
|
||||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
public new static DefAssembly LocalAssebmly { get => (DefAssembly)DefAssemblyBase.LocalAssebmly; set => DefAssemblyBase.LocalAssebmly = value; }
|
|
||||||
|
|
||||||
public Service CfgTargetService { get; private set; }
|
|
||||||
|
|
||||||
private readonly string _patchName;
|
|
||||||
private readonly List<string> _excludeTags;
|
|
||||||
|
|
||||||
public Patch TargetPatch { get; private set; }
|
|
||||||
|
|
||||||
public TimeZoneInfo TimeZone { get; }
|
|
||||||
|
|
||||||
public DefAssembly(string patchName, TimeZoneInfo timezone, List<string> excludeTags, IAgent agent)
|
|
||||||
{
|
|
||||||
this._patchName = patchName;
|
|
||||||
this.TimeZone = timezone;
|
|
||||||
this._excludeTags = excludeTags;
|
|
||||||
this.Agent = agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool NeedExport(List<string> groups)
|
|
||||||
{
|
|
||||||
if (groups.Count == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return groups.Any(g => CfgTargetService.Groups.Contains(g));
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<Patch> _patches = new List<Patch>();
|
|
||||||
|
|
||||||
private readonly List<Service> _cfgServices = new List<Service>();
|
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, TableDataInfo> _recordsByTables = new();
|
|
||||||
|
|
||||||
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
|
|
||||||
|
|
||||||
|
|
||||||
public Patch GetPatch(string name)
|
|
||||||
{
|
|
||||||
return _patches.Find(b => b.Name == name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddCfgTable(DefTable table)
|
|
||||||
{
|
|
||||||
if (!CfgTables.TryAdd(table.FullName, table))
|
|
||||||
{
|
|
||||||
throw new Exception($"table:'{table.FullName}' duplicated");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefTable GetCfgTable(string name)
|
|
||||||
{
|
|
||||||
return CfgTables.TryGetValue(name, out var t) ? t : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
|
||||||
{
|
|
||||||
_recordsByTables[table.FullName] = new TableDataInfo(table, mainRecords, patchRecords);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Record> GetTableAllDataList(DefTable table)
|
|
||||||
{
|
|
||||||
return _recordsByTables[table.FullName].MainRecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableDataInfo GetTableDataInfo(DefTable table)
|
|
||||||
{
|
|
||||||
return _recordsByTables[table.FullName];
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DefTable> GetExportTables()
|
|
||||||
{
|
|
||||||
return Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DefTypeBase> GetExportTypes()
|
|
||||||
{
|
|
||||||
var refTypes = new Dictionary<string, DefTypeBase>();
|
|
||||||
var targetService = CfgTargetService;
|
|
||||||
foreach (var refType in targetService.Refs)
|
|
||||||
{
|
|
||||||
if (!this.Types.ContainsKey(refType))
|
|
||||||
{
|
|
||||||
throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 类型不存在");
|
|
||||||
}
|
|
||||||
if (!refTypes.TryAdd(refType, this.Types[refType]))
|
|
||||||
{
|
|
||||||
throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 重复引用");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var e in this.Types)
|
|
||||||
{
|
|
||||||
if (!refTypes.ContainsKey(e.Key) && (e.Value is DefEnum))
|
|
||||||
{
|
|
||||||
refTypes.Add(e.Key, e.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var table in GetExportTables())
|
|
||||||
{
|
|
||||||
refTypes[table.FullName] = table;
|
|
||||||
table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return refTypes.Values.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Load(string outputService, Defines defines)
|
|
||||||
{
|
|
||||||
SupportDatetimeType = true;
|
|
||||||
|
|
||||||
TopModule = defines.TopModule;
|
|
||||||
|
|
||||||
CfgTargetService = defines.Services.Find(s => s.Name == outputService);
|
|
||||||
|
|
||||||
if (CfgTargetService == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"service:{outputService} not exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_patchName))
|
|
||||||
{
|
|
||||||
TargetPatch = defines.Patches.Find(b => b.Name == _patchName);
|
|
||||||
if (TargetPatch == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"patch '{_patchName}' not in valid patch set");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._patches.AddRange(defines.Patches);
|
|
||||||
|
|
||||||
foreach (var e in defines.Enums)
|
|
||||||
{
|
|
||||||
AddType(new DefEnum(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var b in defines.Beans)
|
|
||||||
{
|
|
||||||
AddType(new DefBean((CfgBean)b));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var p in defines.Tables)
|
|
||||||
{
|
|
||||||
var table = new DefTable(p);
|
|
||||||
AddType(table);
|
|
||||||
AddCfgTable(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
_cfgServices.AddRange(defines.Services);
|
|
||||||
|
|
||||||
foreach (var type in Types.Values)
|
|
||||||
{
|
|
||||||
type.AssemblyBase = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var type in Types.Values)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
s_logger.Trace("precompile type:{0} begin", type.FullName);
|
|
||||||
type.PreCompile();
|
|
||||||
s_logger.Trace("precompile type:{0} end", type.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
this.Agent.Error("precompile type:{0} error", type.FullName);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var type in Types.Values)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
s_logger.Trace("compile type:{0} begin", type.FullName);
|
|
||||||
type.Compile();
|
|
||||||
s_logger.Trace("compile type:{0} end", type.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
this.Agent.Error("compile type:{0} error", type.FullName);
|
|
||||||
s_logger.Error("compile type:{0} error", type.FullName);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var type in Types.Values)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
s_logger.Trace("post compile type:{0} begin", type.FullName);
|
|
||||||
type.PostCompile();
|
|
||||||
s_logger.Trace("post compile type:{0} end", type.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
this.Agent.Error("post compile type:{0} error", type.FullName);
|
|
||||||
s_logger.Error("post compile type:{0} error", type.FullName);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 丑陋. 怎么写更好?
|
|
||||||
|
|
||||||
// 递归 设置DefBean及DefField 的 IsMultiRow
|
|
||||||
|
|
||||||
MarkMultiRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MarkMultiRows()
|
|
||||||
{
|
|
||||||
var multiRowBeans = new HashSet<DefBean>();
|
|
||||||
for (bool anyMark = true; anyMark;)
|
|
||||||
{
|
|
||||||
anyMark = false;
|
|
||||||
foreach (var type in this.Types.Values)
|
|
||||||
{
|
|
||||||
if (type is DefBean beanType && !beanType.IsMultiRow)
|
|
||||||
{
|
|
||||||
bool isMultiRows;
|
|
||||||
if (beanType.IsNotAbstractType)
|
|
||||||
{
|
|
||||||
isMultiRows = beanType.HierarchyFields.Any(f => ((DefField)f).ComputeIsMultiRow());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isMultiRows = beanType.HierarchyNotAbstractChildren.Any(c => ((DefBean)c).IsMultiRow);
|
|
||||||
}
|
|
||||||
if (isMultiRows)
|
|
||||||
{
|
|
||||||
beanType.IsMultiRow = true;
|
|
||||||
//s_logger.Info("bean:{bean} is multi row", beanType.FullName);
|
|
||||||
anyMark = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
using Luban.Common.Utils;
|
|
||||||
using Luban.Job.Cfg.DataCreators;
|
|
||||||
using Luban.Job.Cfg.Datas;
|
|
||||||
using Luban.Job.Cfg.RawDefs;
|
|
||||||
using Luban.Job.Common.Defs;
|
|
||||||
using Luban.Job.Common.Types;
|
|
||||||
using Luban.Job.Common.TypeVisitors;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Luban.Job.Cfg.Defs
|
|
||||||
{
|
|
||||||
public class DefField : DefFieldBase
|
|
||||||
{
|
|
||||||
public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase;
|
|
||||||
|
|
||||||
|
|
||||||
public bool RawIsMultiRow { get; }
|
|
||||||
|
|
||||||
public bool IsMultiRow { get; private set; }
|
|
||||||
|
|
||||||
public bool ComputeIsMultiRow()
|
|
||||||
{
|
|
||||||
if (IsMultiRow)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (CType)
|
|
||||||
{
|
|
||||||
case TBean b: { return IsMultiRow = ((DefBean)b.Bean).IsMultiRow; }
|
|
||||||
case TList b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
|
||||||
case TArray b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
|
||||||
case TMap b: { return IsMultiRow = b.ValueType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string Index { get; }
|
|
||||||
|
|
||||||
public List<string> Groups { get; }
|
|
||||||
|
|
||||||
public DefField IndexField { get; private set; }
|
|
||||||
|
|
||||||
|
|
||||||
public string Sep { get; set; }
|
|
||||||
|
|
||||||
// 如果没有指定sep
|
|
||||||
// 如果是bean,且指定了sep,则使用此值
|
|
||||||
// 如果是vectorN,使用 ,
|
|
||||||
public string ActualSep => string.IsNullOrWhiteSpace(Sep) ? (CType is TBean bean ? ((DefBean)bean.Bean).Sep : "") : Sep;
|
|
||||||
|
|
||||||
public bool NeedExport => Assembly.NeedExport(this.Groups);
|
|
||||||
|
|
||||||
public TEnum Remapper { get; private set; }
|
|
||||||
|
|
||||||
public CfgField RawDefine { get; }
|
|
||||||
|
|
||||||
public string GetTextKeyName(string name) => name + TText.L10N_FIELD_SUFFIX;
|
|
||||||
|
|
||||||
public bool GenTextKey => this.CType is TText;
|
|
||||||
|
|
||||||
|
|
||||||
public string DefaultValue { get; }
|
|
||||||
|
|
||||||
public DType DefalutDtypeValue { get; private set; }
|
|
||||||
|
|
||||||
public bool IsRowOrient { get; }
|
|
||||||
|
|
||||||
public DefField(DefTypeBase host, CfgField f, int idOffset) : base(host, f, idOffset)
|
|
||||||
{
|
|
||||||
Index = f.Index;
|
|
||||||
Sep = f.Sep;
|
|
||||||
this.IsMultiRow = this.RawIsMultiRow = f.IsMultiRow;
|
|
||||||
this.Groups = f.Groups;
|
|
||||||
this.RawDefine = f;
|
|
||||||
this.DefaultValue = f.DefaultValue;
|
|
||||||
this.IsRowOrient = f.IsRowOrient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Compile()
|
|
||||||
{
|
|
||||||
base.Compile();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(this.DefaultValue))
|
|
||||||
{
|
|
||||||
this.DefalutDtypeValue = CType.Apply(StringDataCreator.Ins, this.DefaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (CType)
|
|
||||||
{
|
|
||||||
case TArray t:
|
|
||||||
{
|
|
||||||
if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0)
|
|
||||||
{
|
|
||||||
throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean");
|
|
||||||
}
|
|
||||||
if (t.ElementType is TText)
|
|
||||||
{
|
|
||||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TList t:
|
|
||||||
{
|
|
||||||
if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0)
|
|
||||||
{
|
|
||||||
throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean");
|
|
||||||
}
|
|
||||||
if (t.ElementType is TText)
|
|
||||||
{
|
|
||||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TSet t:
|
|
||||||
{
|
|
||||||
if (t.ElementType is TText)
|
|
||||||
{
|
|
||||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TMap t:
|
|
||||||
{
|
|
||||||
if (t.KeyType is TText)
|
|
||||||
{
|
|
||||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container key type can't text");
|
|
||||||
}
|
|
||||||
if (t.ValueType is TText)
|
|
||||||
{
|
|
||||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container value type can't text");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsMultiRow && !CType.IsCollection && !CType.IsBean)
|
|
||||||
{
|
|
||||||
throw new Exception($"只有容器类型才支持 multi_line 属性");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Sep) && CType is TBean bean)
|
|
||||||
{
|
|
||||||
Sep = bean.GetBeanAs<DefBean>().Sep;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(Index))
|
|
||||||
{
|
|
||||||
if ((CType is TArray tarray) && (tarray.ElementType is TBean b))
|
|
||||||
{
|
|
||||||
if ((IndexField = b.GetBeanAs<DefBean>().GetField(Index)) == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((CType is TList tlist) && (tlist.ElementType is TBean tb))
|
|
||||||
{
|
|
||||||
if ((IndexField = tb.GetBeanAs<DefBean>().GetField(Index)) == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. only array:bean or list:bean support index");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(this.RawDefine.Converter))
|
|
||||||
{
|
|
||||||
this.Remapper = AssemblyBase.GetDefTType(HostType.Namespace, this.RawDefine.Converter, this.IsNullable) as TEnum;
|
|
||||||
if (this.Remapper == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' converter:'{this.RawDefine.Converter}' not exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
using Luban.Common.Utils;
|
|
||||||
using Luban.Server.Common;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Luban.Job.Common.Defs
|
|
||||||
{
|
|
||||||
public abstract class DefTypeBase
|
|
||||||
{
|
|
||||||
public DefAssemblyBase AssemblyBase { get; set; }
|
|
||||||
|
|
||||||
public int Id { get; protected set; }
|
|
||||||
|
|
||||||
public string TopModule => AssemblyBase.TopModule;
|
|
||||||
|
|
||||||
public IAgent Agent => AssemblyBase.Agent;
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string Namespace { get; set; }
|
|
||||||
|
|
||||||
public string FullName => TypeUtil.MakeFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string NamespaceWithTopModule => TypeUtil.MakeNamespace(AssemblyBase.TopModule, Namespace);
|
|
||||||
|
|
||||||
public string FullNameWithTopModule => TypeUtil.MakeFullName(AssemblyBase.TopModule, FullName);
|
|
||||||
|
|
||||||
public string JavaFullName => TypeUtil.MakeFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string GoFullName => TypeUtil.MakeGoFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string GoPkgName => TypeUtil.MakeGoPkgName(Namespace);
|
|
||||||
|
|
||||||
public string CppNamespaceBegin => TypeUtil.MakeCppNamespaceBegin(Namespace);
|
|
||||||
|
|
||||||
public string CppNamespaceEnd => TypeUtil.MakeCppNamespaceEnd(Namespace);
|
|
||||||
|
|
||||||
public string CppFullNameWithTopModule => TypeUtil.MakeCppFullName(AssemblyBase.TopModule, FullName);
|
|
||||||
|
|
||||||
public string TypescriptNamespaceBegin => TypeUtil.MakeTypescriptNamespaceBegin(Namespace);
|
|
||||||
|
|
||||||
public string TypescriptNamespaceEnd => TypeUtil.MakeTypescriptNamespaceEnd(Namespace);
|
|
||||||
|
|
||||||
public string CppFullName => TypeUtil.MakeCppFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string PyFullName => TypeUtil.MakePyFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name);
|
|
||||||
|
|
||||||
public string Comment { get; protected set; }
|
|
||||||
|
|
||||||
public Dictionary<string, string> Tags { get; protected set; }
|
|
||||||
|
|
||||||
public bool HasTag(string attrName)
|
|
||||||
{
|
|
||||||
return Tags != null && Tags.ContainsKey(attrName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetTag(string attrName)
|
|
||||||
{
|
|
||||||
return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void PreCompile() { }
|
|
||||||
|
|
||||||
public abstract void Compile();
|
|
||||||
|
|
||||||
public virtual void PostCompile() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue