如何删除C#中的强类型?

时间:2015-09-23 18:19:32

标签: c#

让我们说我必须将从数据库中读取的内容转换为对象。我可能会有这样的事情:

public class Foo {

    int a;
    DateTime b;
    float c;

    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    internal Foo(DataRow dr) {
        this.a = (int) dr["a"];
        this.b = (DateTime) dr["b"];
        this.c = (float) dr["c"];
    }

}

您可以使用dynamic关键字做一些可以删除类型检查并自动转换的内容吗?理想情况下,它只适用于internal构造函数。

2 个答案:

答案 0 :(得分:3)

你的意思是这样吗?

public class Foo {
    dynamic a;
    dynamic b;
    dynamic c;

    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    internal Foo(DataRow dr) {
        this.a = dr["a"];
        this.b = dr["b"];
        this.c = dr["c"];
    }
}

当然,你可以这样做,如果你真的讨厌那么多,然后编译器就不再是你最好的朋友,以防止你在脚下射击。

如果摆脱丑陋的演员是你的主要关注点,另一种方法是使用DataRowExtensions.Field<T>方法扩展。

  

提供对指定行中每个列值的强类型访问。

用法示例:

public class Foo {
    int a;
    DateTime b;
    float c;

    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    internal Foo(DataRow dr) {
        this.a = dr.Field<int>("a");
        this.b = dr.Field<DateTime>("b");
        this.c = dr.Field<float>("c");
    }
}

答案 1 :(得分:1)

您可以围绕DataRow实施动态包装(警告:未经测试的代码)

public class DynamicDataRow : DynamicObject
{
    private DataRow _dataRow;

    public DynamicDataRow(DataRow dataRow)
    {
        if (dataRow == null)
            throw new ArgumentNullException("dataRow");
        this._dataRow = dataRow;
    }

    public DataRow DataRow
    {
        get { return _dataRow; }
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            result = _dataRow[binder.Name];
            return true;
        }
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            _dataRow[binder.Name] = value;
            return true;
        }
        return false;
    }
}

然后按如下方式修改内部构造函数:

internal Foo(DynamicDataRow ddr) {
    dynamic dr = ddr;
    this.a = dr.a;
    this.b = dr.b;
    this.c = dr.c;
}

并用

调用它
var foo = new Foo(new DynamicDataRow(someDataRowObject));

与sstan的答案不同,您将失去编译时类型检查的所有好处。前端听起来很糟糕,但实际上并不是那么糟糕,因为即使使用DataRowExtensions.Field<T>扩展方法,类型检查仍然会在运行时发生,因为编译器无法进行检查数据库中列的数据类型是否与您尝试将该信息填入的字段匹配。所以无论哪种方式都会进行运行时类型检查。