如何在数据表行中存储多列对象

本文关键字:存储 对象 数据表 | 更新日期: 2023-09-27 18:13:39

我如何存储对象在数据表行扩展到几列或有对象在一列和引用属性到这个对象在其他?

class MyDataTable : DataTable
{
    public MyDataTable
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2")        
        this.Columns.Add("Cat", typeof(Cat))
        this.Columns.Add("CatType")
        Cat cat1 = new Cat("name1", "type1")
        Cat cat2 = new Cat("name2", "type2")
        this.Rows.add(new object[] {"value","value",cat1,cat1.type} )
        this.Rows.add(new object[] {"value","value",cat2,cat2.type} )
        // I want to show table like: 
        // |value|value|name1|type1|
        // |value|value|name2|type2|
        // while type should be a reference not a static string, so
        cat1.type = "type3"; //should be able to change table like:
        // |value|value|name1|type3|
        // |value|value|name2|type2|    
    }
} 
class Cat
{
    string name;
    string type;
    public Cat(...){..}
    public override string toString()
        return name;
}

或者像表中表这样的东西?:

class MyDataTable : DataTable
{
    public MyDataTable
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2")        
        this.Columns.Add("Cat", typeof(Cat))
        Cat cat1 = new Cat("name1", "type1")
        Cat cat2 = new Cat("name2", "type2")
        this.Rows.add(new object[] {"value","value",cat1} )
        this.Rows.add(new object[] {"value","value",cat2} )
        // And show table like: 
        // |value|value||name1|type1||
        // |value|value||name2|type2||
    }
} 
 class Cat : DataTable {
      public Cat(string name, string type){
        this.Columns.Add("name");
        this.Columns.Add("type");
        this.Rows.Add(name,type);
      } 
 }

但是能够在:

中显示Cat列
 datagridview1.DataSource = new MyDataTable();

////

@rene回答

当我设置'type'为LiveString而有:

datagridview.datasource = new List<Cat>(...)

并尝试从与此对象关联的datagridview GUI单元格编辑,我得到:

System.FormatException: Invalid cast from 'System.String' to 'syb_con.LiveString'. ---> System.InvalidCastException: Invalid cast from 'System.String' to 'syb_con.LiveString'.
  at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Windows.Forms.Formatter.ChangeType(Object value, Type type, IFormatProvider formatInfo)
   --- End of inner exception stack trace ---
   at System.Windows.Forms.Formatter.ChangeType(Object value, Type type, IFormatProvider formatInfo)
   at System.Windows.Forms.Formatter.ParseObjectInternal(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue)
   at System.Windows.Forms.Formatter.ParseObject(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue, Object dataSourceNullValue)
   at System.Windows.Forms.DataGridViewCell.ParseFormattedValueInternal(Type valueType, Object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
   at System.Windows.Forms.DataGridViewCell.ParseFormattedValue(Object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
   at System.Windows.Forms.DataGridView.PushFormattedValue(DataGridViewCell& dataGridViewCurrentCell, Object formattedValue, Exception& exception)

如何在数据表行中存储多列对象

DataTable的真正目的是存储添加行时的状态。您的用例似乎超出了它的设计能力。

如果允许将Type属性的不可变类型字符串替换为允许更改其值的类型,则用于添加对象的技巧也可以用于类型。对于Object类型的dataccolumns, Row将调用该对象的ToString

我将引入一个新的类型LiveString

class LiveString 
{
    string value;
    internal string Value {
        get{return value;}
        set{this.value= value;}
    }
    public LiveString(string value) {
       this.value = value;
    }
    // use an implicit operator
    public static implicit operator LiveString(string value)
    {
        return new LiveString(value);
    }
    public override string ToString() {
        return value;
    }
}

它的目的是包装一个字符串,并有方法从字符串创建新的对象,但也获取和改变其内部状态。我使用了一个转换操作符,因此Cat类的当前用户不必更改太多代码。

你必须调整你的代码如下:

class MyDataTable : DataTable
{
    public MyDataTable()
    {
        this.Columns.Add("col1");
        this.Columns.Add("col2");        
        this.Columns.Add("Cat", typeof(Cat));
        // notice the typeof here
        this.Columns.Add("CatType", typeof(LiveString));
        Cat cat1 = new Cat("name1", "type1");
        Cat cat2 = new Cat("name2", "type2");
        this.Rows.Add(new object[] {"value","value",cat1,cat1.type} );
        this.Rows.Add(new object[] {"value","value",cat2,cat2.type} );
        cat1.type = "type3"; 
    }
} 

和Cat类。注意,在类型的setter上,我没有替换_type上的当前对象,而只是替换它的Value。这保证了Row所持有的实例得到更新,而不是被替换为一个不在Row中存储或更新的新实例。

class Cat
{
    string name;
    LiveString _type;
    public LiveString type {
        get 
        { 
            return _type;
        }
        set 
        {
            _type.Value = value.Value;
        }
    }
    public Cat(string name, string type){this.name= name; this._type = type;}
    public override string ToString()
    {
        return name;
    }
}

这个例子试图尽可能接近DataTable的使用。相反,您可以构建自己的Collection,并为其提供有关其保存的类型以及希望如何表示它们的元数据。我认为lambda表达式在实现空间中是有用的。其他选项可能是使用反射