【问题标题】:Dynamic DataTable and DataRow creation from class从类创建动态 DataTable 和 DataRow
【发布时间】:2013-09-16 17:08:11
【问题描述】:

我有许多不同大小和类型的类,我正在尝试获取一个通用脚本来填充它们。

请考虑以下代码。我遇到的问题是最后它只打印列名(正确)但没有值。

在单步执行代码时,我可以看到它认为我在 createDataRow 方法中传递的类型是空的,我不明白为什么。

public class tables { }
public class Dog : tables
{
    public string Breed { get; set; }
    public string Name { get; set; }
    public int legs { get; set; }
    public bool tail { get; set; }
}



class Program
{
    public static DataTable CreateDataTable(Type animaltype)
    {
        DataTable return_Datatable = new DataTable();
        foreach (PropertyInfo info in animaltype.GetProperties())
        {
            return_Datatable.Columns.Add(new DataColumn(info.Name, info.PropertyType));
        }
        return return_Datatable;
    }

    public static DataRow createDataRow(tables dog, DataTable touse) //This is half of the problem
    {
        Type type = dog.GetType();
        DataRow x = touse.NewRow();

        foreach (PropertyInfo prop in typeof(tables).GetProperties()) //this is the other half of the problem
        {
            x[prop.Name] = prop.GetValue(dog, null);
        }

        return x;
    }

    static void Main(string[] args)
    {
        Dog Killer = new Dog();
        Killer.Breed = "Maltese Poodle";
        Killer.legs = 3;
        Killer.tail = false;
        Killer.Name = "Killer";

        DataTable dogTable = new DataTable();
        dogTable = CreateDataTable(typeof(Dog));
        DataRow dogRow = dogTable.NewRow();
        dogRow = createDataRow(Killer, dogTable); //This is where I pass the data
        dogTable.Rows.Add(dogRow);

        foreach (DataRow row in dogTable.Rows)
        {
            foreach (DataColumn col in dogTable.Columns)
            {
                Console.WriteLine("Column {0} =" + row[col].ToString(),col.ColumnName);
            }
        }
        Console.ReadLine();

    }      
}

现在,如果我要更改以下内容:

 public static DataRow createDataRow(tables dog, DataTable touse)

 public static DataRow createDataRow(Dog dog, DataTable touse)

foreach (PropertyInfo prop in typeof(tables).GetProperties())

foreach (PropertyInfo prop in typeof(Dog).GetProperties())

...一切正常。
但我不想这样做,因为这意味着我必须为我拥有数百个类的每个类创建一个“createDataRow”函数。

我做错了什么?

【问题讨论】:

    标签: c# class generics methods types


    【解决方案1】:

    我把它舔了!

    所以诀窍是在 CreateDataRow 方法中将类作为对象传递。

    namespace Generics
    

    {

    public class Dog
    {
        public string Breed { get; set; }
        public string Name { get; set; }
        public int legs { get; set; }
        public bool tail { get; set; }   
    
    }
    
    public class Cat
    {
        public string Breed { get; set; }
        public string Name { get; set; }
        public int toes { get; set; }
        public bool Aggressive { get; set; }
        public bool tail { get; set; }
    }
    
    
    
    class Program
    {
    
    
        public static DataTable CreateDataTable(Type animaltype)
        {
    
            DataTable return_Datatable = new DataTable();
            foreach (PropertyInfo info in animaltype.GetProperties())
            {
                return_Datatable.Columns.Add(new DataColumn(info.Name, info.PropertyType));
            }
            return return_Datatable;
        }
    
    
        public static DataRow makeRow(object input, DataTable table)
        {
            Type inputtype = input.GetType();
            DataRow row = table.NewRow();
            foreach (PropertyInfo info in inputtype.GetProperties())
            {
                row[info.Name] = info.GetValue(input, null);
            }
            return row;
        }
    
        static void Main(string[] args)
        {
            Cat Dexter = new Cat();
            Dexter.Breed = "Bengal";
            Dexter.toes = 12;
            Dexter.tail = false;
            Dexter.Name = "Killer";
            Dexter.Aggressive = true;
    
            Dog Killer = new Dog();            
            Killer.Breed = "Maltese Poodle";
            Killer.legs = 3;
            Killer.tail = false;
            Killer.Name = "Killer";       
    
            DataTable dogTable = CreateDataTable(typeof(Dog));
            dogTable.Rows.Add(makeRow(Killer, dogTable));
    
            DataTable catTable = CreateDataTable(typeof(Cat));
            catTable.Rows.Add(makeRow(Dexter, catTable));
    
    
            foreach (DataRow rows in catTable.Rows)
            {
                foreach (DataColumn col in catTable.Columns)
                {
                    Console.WriteLine("Column {0} =" + rows[col].ToString(), col.ColumnName.PadRight(15));
                }
            }
    
    
            foreach (DataRow rows in dogTable.Rows)
            {
                foreach (DataColumn col in dogTable.Columns)
                {
                    Console.WriteLine("Column {0} =" + rows[col].ToString(),col.ColumnName.PadRight(15));
                }
            }
            Console.ReadLine();
    
        }      
    }
    

    【讨论】:

    • @spenti43,所以我将类作为对象传递给makerow,然后获取类型。从中我可以获取属性。
    【解决方案2】:

    为什么需要这个功能?

    public static DataRow createDataRow(Dog dog, DataTable touse)
    

    Dog 是从表中派生出来的,所以你可以这样使用:

    public static DataRow createDataRow(tables dog, DataTable touse)
    

    如果你有不同的实现,你可以重写基方法,但在这种情况下你必须把它变成虚拟的(并在基类中声明基方法):

    public virtual DataRow createDataRow(DataTable touse)
    

    如果你想享受多态性的好处,不要让它成为静态的。

    您不必传递表格实例,只需调用实例即可:

    tables foo = new Dog();
    var dr = foo.createDataRow(return_Datatable);
    

    类:

    public class tables 
    { 
        public virtual DataRow createDataRow(DataTable touse)
        {
           //base implementation
        }
    
    }
    
    public class Dog : tables
    {
        public string Breed { get; set; }
        public string Name { get; set; }
        public int legs { get; set; }
        public bool tail { get; set; }
        public override DataRow createDataRow(DataTable touse)
        {
           //derived implementation
        }
    }
    

    【讨论】:

    • 谢谢@speti43,但是我认为我的“tables foo = new Dog()”语句有问题。当我这样做时,它无法识别主块代码中的任何 Dog 属性。
    • 当然可以,因为你还没有在基类中声明属性。因此它是派生类实例中的基类类型,它不知道派生类的属性。所以你必须在基类中声明属性,如果你想在所有派生类中使用它。基类是属性和方法的“契约”。如果你把一些东西放到基类中,你可以肯定,它也会在所有派生类中。也许有不同的实现,但没关系
    • 啊,是的!很明显,对此感到抱歉。然而,这给我带来了一个问题。就像我说的那样,我有数百个(以及 143 个)课程。并且每个类的属性都不一样。也许我应该尝试扭转两者之类的东西
    • 如果你的代码是多余的,可能会有问题,但如果你有完全不同的类成员,你不能用继承来优化它。
    • 好的,是时候重新考虑一下了。谢谢你的帮助。我会接受你的回答,因为即使我的解决方案有缺陷,它仍然有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2012-12-07
    • 2020-02-27
    • 1970-01-01
    • 2011-05-12
    • 2020-03-28
    相关资源
    最近更新 更多