简体   繁体   中英

How to extend DataRow and DataTable in C# with additional properties and methods?

I would like create a custom DataRow that will have -let's say- a propery called IsCheapest.

public class RateDataRow : DataRow
{
    protected internal RateDataRow(DataRowBuilder builder) : base(builder)
    {
    }

    public bool IsCheapest { get; set ;}
}

And I want to have a new DataTable that contains only ***RateDataRow***s so that .NewDataRow() returns RateDataRow instance as a new row.

what should be the implementation on the class that extends DataTable?

Thanks,

I know this is an old post now but I couldn't get the example above to work. I had a similar problem so was keen to find a solution. After a bit of research I found the following to work:

class Program
{
    static void Main(string[] args)
    {
        MyDataTable t1 = new MyDataTable();

        t1.Columns.Add(new DataColumn("Name", typeof(string)));
        t1.Columns.Add(new DataColumn("DateOfBirth", typeof(DateTime)));

        MyDataRow r1 = t1.NewRow() as MyDataRow;
        r1["Name"] = "Bob";
        r1["DateOfBirth"] = new DateTime(1970, 5, 12);
        t1.Rows.Add(r1);
    }
}

[Serializable]
public class MyDataTable : DataTable
{
    public MyDataTable()
        : base()
    {
    }

    public MyDataTable(string tableName)
        : base(tableName)
    {
    }

    public MyDataTable(string tableName, string tableNamespace)
        : base(tableName, tableNamespace)
    {
    }

    /// <summary>
    /// Needs using System.Runtime.Serialization;
    /// </summary>
    public MyDataTable(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }

    protected override Type GetRowType()
    {
        return typeof(MyDataRow);
    }

    protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
    {
        return new MyDataRow(builder);
    }
}

[Serializable]
public class MyDataRow : DataRow
{
    public bool MyPropertyThatIdicatesSomething { get; private set; }

    public MyDataRow()
        : base(null)
    {
    }

    public MyDataRow(DataRowBuilder builder)
        : base(builder)
    {
    }
}

The DataTable exposes a GetRowType virtual method, override this in a derived class. Any attempts to add a row of the wrong type will throw an exception:

class Program
{
    static void Main(string[] args)
    {
        MyDataTable t = new MyDataTable();
        t.Rows.Add(t.NewRow()); // <-- Exception here, wrong type (base doesn't count).
    }
}

public class MyDataTable : DataTable
{
    public MyDataTable()
        : base()
    { }

    protected override Type GetRowType()
    {
        return typeof(MyDataRow);
    }
}

public class MyDataRow : DataRow
{
    public MyDataRow()
        : base(null)
    { }
}

From your question it's not clear if you are familiar with Typed Datasets. They basically are what you are asking for.

You could use the built-in wizards to create a Typed Dataset based on an XSD (and the XSD is extracted from the Db schema). In a WinForms project, select "Add DataSource" and follow the steps.

Even if you don't want to use that model you could borrow from the code for properties, partial classes etc.

It would be wise to either use that model or stay very close to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM