我也想过不用继承而用包含,但总觉得隔了一层,不爽!
我的目的是对datatable进行增强,并以属性的形式提供对特定字段的访问

解决方案 »

  1.   

    这个是我用工具生成的代码,你自己查考一下吧: ///<summary>ClassATable</summary>
    [Serializable] public class ClassATable : DataTable
    {
    ///<summary>.ctor</summary>
    public ClassATable():base("ClassA")
    {
    DataColumn dc;
    dc=new DataColumn("id",typeof(System.Int32));
    dc.AutoIncrement=true;
    dc.ReadOnly=true;
    dc.Unique=true;
    dc.AllowDBNull=false;
    Columns.Add(dc);
    dc=new DataColumn("Aname",typeof(System.String));
    dc.AllowDBNull=false;
    Columns.Add(dc);
    }
    ///<summary>Deserialization .ctor</summary>
    public ClassATable(SerializationInfo info, StreamingContext context):base(info,context)
    {
    }
    /// <summary>copy from datarow</summary>
    static public ClassA CopyRow(DataRow row)
    {
    if(row==null)throw(new ArgumentNullException("row"));
    ClassATable dt=new ClassATable();
    dt.ImportRow(row);
    return dt[0];
    }
    DataRowBuilder newbuilder;
    internal DataRowBuilder GetRowBuilder(){NewRow();return newbuilder;}
    ///<summary>new row</summary>
    protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
    {
    newbuilder=builder;
    return new ClassA(builder);
    }
    ///<summary>get Rows.Count</summary>
    public int Count
    {
    get
    {
    return Rows.Count;
    }
    }
    ///<summary>get ClassA</summary>
    public ClassA this[int index]
    {
    get
    {
    return (ClassA)Rows[index];
    }
    }
    }
    ///<summary>ClassA</summary>
    [Serializable] public class ClassA : DataRow , ISerializable
    {
    internal ClassA(DataRowBuilder builder):base(builder){}
    ///<summary>Deserialization .ctor</summary>
    public ClassA(SerializationInfo info, StreamingContext context):this(MakeRowInfo(info))
    {
    }
    private ClassA(RowInfo ri):base(ri.builder)
    {
    DataRow oldrow=ri.table[0];
    this.ItemArray=oldrow.ItemArray;
    ri.table.Rows.RemoveAt(0);
    ri.table.Rows.Add(this);
    }
    private struct RowInfo
    {
    public RowInfo(ClassATable t)
    {
    table=t;
    builder=t.GetRowBuilder();
    }
    public DataRowBuilder builder;
    public ClassATable table;
    }
    static RowInfo MakeRowInfo(SerializationInfo info)
    {
    return new RowInfo((ClassATable)info.GetValue("Table",typeof(ClassATable)));
    }
    void ISerializable.GetObjectData(SerializationInfo info,StreamingContext context)
    {
    info.AddValue("Table",ClassATable.CopyRow(this).Table);
    }
    ///<summary> get ClassATable</summary>
    new public ClassATable Table
    {
    get
    {
    return (ClassATable)base.Table;
    }
    }
    ///<summary>id</summary>
    [SoapIgnore]
    public SqlInt32 sql_id
    {
    get
    {
    if(this.IsNull("id"))
    return SqlInt32.Null;
    return new SqlInt32((Int32)this["id"]);
    }
    set
    {
    if(value.IsNull)
    throw new InvalidOperationException("not allow null");
    else
    this["id"]=value.Value;
    }
    }
    ///<summary>id</summary>
    [SoapIgnore]
    public object object_id
    {
    get
    {
    return this["id"];
    }
    set
    {
    if(value==null||Convert.IsDBNull(value))
    throw new InvalidOperationException("not allow null");
    else
    this["id"]=Convert.ToInt32(value);
    }
    }
    ///<summary>id</summary>
    [SoapIgnore]
    public Int32 value_id
    {
    get
    {
    return new SqlInt32((Int32)this["id"]).Value;
    }
    set
    {
    this["id"]=value;
    }
    }
    ///<summary>Aname</summary>
    [SoapIgnore]
    public SqlString sql_Aname
    {
    get
    {
    if(this.IsNull("Aname"))
    return SqlString.Null;
    return new SqlString((String)this["Aname"]);
    }
    set
    {
    if(value.IsNull)
    throw new InvalidOperationException("not allow null");
    else
    this["Aname"]=value.Value;
    }
    }
    ///<summary>Aname</summary>
    [SoapIgnore]
    public object object_Aname
    {
    get
    {
    return this["Aname"];
    }
    set
    {
    if(value==null||Convert.IsDBNull(value))
    throw new InvalidOperationException("not allow null");
    else
    this["Aname"]=Convert.ToString(value);
    }
    }
    ///<summary>Aname</summary>
    [SoapIgnore]
    public String value_Aname
    {
    get
    {
    return new SqlString((String)this["Aname"]).Value;
    }
    set
    {
    if(value==null)
    throw new InvalidOperationException("not allow null");
    else
    this["Aname"]=value;
    }
    }
    }
      

  2.   

    see Serializing DataTable Objects inBinary Serialization of ADO.NET Objects
    http://msdn.microsoft.com/msdnmag/issues/02/12/CuttingEdge/default.aspx