C# 嵌套列表<&燃气轮机;抽象类的属性
谢谢你的回复,非常好。然而,在更深入地阅读HashPsi初始评论时,我发现有几个用户都希望将此应用程序与几个不同但非常相似的报告一起使用,例如,有更多的可用列可以包含/删除在特定于用户的任何报告中 每个用户只需查看他们的数据并选择最初导入数据的过滤器,而不是为每个用户类型制定解决方案。 为了在下面的行级编辑中保持非常简单,我设置了一个非常简单的id和20x字符串,然后列出pre-parse的货币/数字,可用于选择下拉数字过滤器或值之间的范围。类似的列表用于工作表级别的字符串下拉列表 完成的应用程序将使用一个由工作表id分隔的数据库(或类似数据库)。 你的想法是什么,我是否应该使用更多的泛型,比如下面的例子(这些例子很好,虽然有点先进,但我还是一个差劲的笨蛋:)C# 嵌套列表<&燃气轮机;抽象类的属性,c#,list,generics,abstract-class,C#,List,Generics,Abstract Class,谢谢你的回复,非常好。然而,在更深入地阅读HashPsi初始评论时,我发现有几个用户都希望将此应用程序与几个不同但非常相似的报告一起使用,例如,有更多的可用列可以包含/删除在特定于用户的任何报告中 每个用户只需查看他们的数据并选择最初导入数据的过滤器,而不是为每个用户类型制定解决方案。 为了在下面的行级编辑中保持非常简单,我设置了一个非常简单的id和20x字符串,然后列出pre-parse的货币/数字,可用于选择下拉数字过滤器或值之间的范围。类似的列表用于工作表级别的字符串下拉列表 完成的应用程
公共抽象类实体
{
公共虚拟int-Id{get;set;}//todo-autoincrement
}
课程表
{
公共列表行{get;set;}
公共列表ParsedStringList{get;set;}
}
公共类行:实体
{
public int RowId{get;set;}//唯一键
公共字符串String1{get;set;}
公共字符串String2{get;set;}
公共字符串String3{get;set;}
公共字符串String4{get;set;}
公共字符串String5{get;set;}
公共字符串String6{get;set;}
公共字符串String7{get;set;}
公共字符串String8{get;set;}
公共字符串String9{get;set;}
公共字符串String10{get;set;}
公共字符串String11{get;set;}
公共字符串String12{get;set;}
公共字符串String13{get;set;}
公共字符串String14{get;set;}
公共字符串String15{get;set;}
公共字符串String16{get;set;}
公共字符串String17{get;set;}
公共字符串String18{get;set;}
公共字符串String19{get;set;}
公共字符串String20{get;set;}
公共列表ParsedNumber{get;set;}
}
公共类ParsedToNumber
{
公共int列位置{get;set;}
公共十进制数{get;set;}
public int RowId{get;set;}//外键
}
公共类ParsedToStringList
{
公共int列位置{get;set;}
公共列表筛选器字符串{get;set;}
public int RowId{get;set;}//外键
}
公共类过滤器
{
公共字符串筛选器字符串{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var sheet=新的sheet();
sheet.Rows.Add(新行(){
Id=1,RowId=303,String1=“ABC123”,String2=“Abc有限公司”,String3=“£550.00”,
String4=“£150.00”,String5=“批发”,ParsedNumber=新列表(){
新的ParsedToNumber(){ColumnPosition=3,Number=550.00m,RowId=303},
新的ParsedToNumber(){ColumnPosition=4,Number=150.00m,RowId=303}
} });
sheet.Rows.Add(新行(){
Id=2,RowId=607,String1=“XYZ808”,String2=“XYZ无限”,String3=“£999.99”,
String4=“£55.55”,String5=“批发”,ParsedNumber=新列表(){
新的ParsedToNumber(){ColumnPosition=3,Number=999.99m,RowId=607},
新的ParsedToNumber(){ColumnPosition=4,Number=55.55m,RowId=607}
} });
//这提供了字符串格式的数据持久性
//并创建可解析的列的转换
//在下拉列表或范围选择中为将来做好准备。
}
}
我真的在玩这个,需要有新的眼光。我假设我可以将类行中的列表单元格更改为可以使用从抽象类单元格继承的具体对象强制转换的内容
代码的目标是创建一个动态的单元格行,如果可能,可以将其解析为整数、货币、字符串(和其他)类型,并由用户使用。数据从会计数据源的csv文件导入。
我最初创建了一组整数、货币、字符串字段,虽然效率不高,但更简单(如果这种方法更好,请说)
课程表
{
公共列表行{get;set;}
}
公共类行
{
公共字符串伪{get;set;}
公共列表单元格{get;set;}//Intellisence at advisions
}//类型参数的数目不正确?
公共类专栏
{
公共字符串名称{get;set;}
}
公共枚举列类型
{
一串
数字,
通货
}
公共抽象类单元
{
公共列{get;set;}
公共T数据{get;set;}
公共抽象空解析(objectobj);
}
公共类字符串单元格:单元格
{
公共覆盖无效解析(对象obj)
{
抛出新的NotImplementedException();
}
}
您可以这样做,但它需要您将值类型框起来:
public class Row
{
public string Dummy { get; set; }
public List<Cell<Object>> Cells { get; set; }
}
请注意,ContentType
是您的ColumnType
,但重命名的除外。然后你可以像这样拥有你的StringContent
。。。(您可以根据需要更改set
的实现。)
现在,您可以离开单元格
,不必担心其内容(因此您可能不需要将其作为摘要
)
创建对象模型以表示表/电子表格时,通常需要记住两个主要注意事项:
class Sheet
{
public List<Row> Rows { get; set; }
}
public class Row
{
public string Dummy { get; set; }
public List<Cell> Cells { get; set; }//Intellisence at <Cell> advises
} //incorrect number of type parameters?
public class Column
{
public string Name { get; set; }
}
public enum ColumnType
{
String,
Number,
Currency
}
public abstract class Cell<T>
{
public Column Column { get; set; }
public T Data { get; set; }
public abstract void Parse( object obj );
}
public class StringCell : Cell<string>
{
public override void Parse( object obj )
{
throw new NotImplementedException();
}
}
public class Row
{
public string Dummy { get; set; }
public List<Cell<Object>> Cells { get; set; }
}
public abstract class ContentBase
{
public ContentType Type;
public Object Value;
}
public class StringContent : ContentBase
{
private string _value;
public ContentType Type
{
get { return ContentType.String; }
private set;
}
public string Value
{
get { return _value; }
set { _value = (string)value; }
}
}
public abstract class Cell<>
{
public Column Column { get; set; }
public ContentBase Content { get; set; }
}
public class Row
{
public string Dummy { get; set; }
public List<Cell> Cells { get; set; }
}
class Sheet {
public List<Row> Rows { get; set; }
}
public class Row {
public string Dummy { get; set; }
public List<Cell> Cells { get; set; }
}
public class Column {
public string Name { get; set; }
public ValueType ValueType { get; set; }
}
public class Cell {
public Column Column { get; private set; }
public object Data { get; private set; }
public int GetValueInt() {
return Column.ValueType == ValueType.Number ? (int)Data : 0;
}
public string GetValueString() {
// could also return Data.ToString() is Data is not null
return Column.ValueType == ValueType.String ? (string)Data : null;
}
public decimal GetValueCurrenty() {
return Column.ValueType == ValueType.Currency ? (decimal)Data : 0;
}
// factory for cells
public static Cell MakeCell(object data, Column column) {
// fail-early if the data does not match the value type specified by the column
switch (column.ValueType) {
case ValueType.String:
if (!(data is string)) {
throw new ArgumentException("Invalid data for column containing strings");
}
break;
case ValueType.Number:
if (!(data is int)) {
throw new ArgumentException("Invalid data for column containing ints");
}
break;
case ValueType.Currency:
if (!(data is decimal)) {
throw new ArgumentException("Invalid data for column containing decimals");
}
break;
}
var cell = new Cell { Column = column, Data = data };
return cell;
}
public enum ColumnType
{
String,
Date,
Currency
}
public interface IValue
{
void Parse(object obj);
}
public class Sheet
{
public List<Column> Columns { get; set; }
public Column this[int column] { get { return Columns[column]; } set { Columns[column]=value; } }
}
public class Column
{
public string Name { get; set; }
public ColumnType Type { get; set; }
public List<Cell> Rows { get; set; }
public Cell this[int row] { get { return Rows[row]; } set { Rows[row]=value; } }
}
public class Cell
{
public Column Column { get; set; }
public IValue Data { get; set; }
}
public class StringValue : IValue
{
public StringValue(string value) { Value=value; }
public string Value { get; set; }
public void Parse(object obj)
{
Value=obj.ToString();
}
}
public class DecimalValue : IValue
{
public DecimalValue(decimal value) { Value=value; }
public decimal Value { get; set; }
public void Parse(object obj)
{
if(obj is decimal)
{
Value=(decimal)obj;
}
}
}
public class DateValue : IValue
{
public DateValue(DateTime value) { Value=value; }
public DateTime Value { get; set; }
public void Parse(object obj)
{
if(obj is DateTime)
{
Value=(DateTime)obj;
}
}
}
class Program
{
static void Main(string[] args)
{
var sheet=new Sheet() { Columns = new List<Column>() };
sheet.Columns.Add(new Column()
{
Type=ColumnType.String,
Name="Item",
Rows=new List<Cell>()
});
sheet.Columns.Add(new Column()
{
Type=ColumnType.Date,
Name="Date",
Rows=new List<Cell>()
});
sheet.Columns.Add(new Column()
{
Type=ColumnType.Currency,
Name="Amount",
Rows=new List<Cell>()
});
sheet[0].Rows.Add(new Cell() { Column=sheet[0], Data=new StringValue("AAB") });
sheet[0].Rows.Add(new Cell() { Column=sheet[0], Data=new StringValue("AAC") });
sheet[0].Rows.Add(new Cell() { Column=sheet[0], Data=new StringValue("ABA") });
sheet[1].Rows.Add(new Cell() { Column=sheet[1], Data=new DateValue(DateTime.Now) });
sheet[1].Rows.Add(new Cell() { Column=sheet[1], Data=new DateValue(DateTime.Now) });
sheet[1].Rows.Add(new Cell() { Column=sheet[1], Data=new DateValue(DateTime.Now) });
sheet[2].Rows.Add(new Cell() { Column=sheet[2], Data=new DecimalValue(1000m) });
sheet[2].Rows.Add(new Cell() { Column=sheet[2], Data=new DecimalValue(1200m) });
sheet[2].Rows.Add(new Cell() { Column=sheet[2], Data=new DecimalValue(870m) });
sheet[0][1].Data.Parse("CCC");
var check=(sheet[0][1].Data as StringValue).Value;
// check == "CCC"
}
}