您如何处理对象类型切换?

发布于 2024-11-05 19:19:49 字数 2119 浏览 3 评论 0原文

在 C# 中,这个问题时不时就会出现。通常我会得到一个对象值,然后我必须为其调用“真实”函数。像这样的事情:

if (type==typeof(byte))
  val = rs.GetByte(col);
else if (type==typeof(int))
  val = rs.GetInt32(col);
...

或者

if (type==typeof(byte))
  Call((byte)val);
else if (type==typeof(int))
  Call((int)val);
...

我可以在这里看到文本模式,但我没有想出可以一次性处理所有肮脏工作的解决方案。

你如何处理它?<​​/strong>你收到对象值,你必须设置它或传递它,但不是作为对象而是作为具体类型(POD、可为空的 POD 和字符串)并且......?

编辑

完整示例(这是问题的原因):

    protected IRecord ReadRecord()
    {
        if (!ResultSet.Read())
            return null;

        IRecord record = CreateIRecord();

        var type = record.GetType();
        int column = -1;

        foreach (var prop in type.GetProperties())
        {
            ++column;
            object val;

            if (prop.PropertyType == typeof(byte))
                val = ResultSet.GetByte(column);
            else if (prop.PropertyType == typeof(byte?))
                val = ResultSet.GetSqlByte(column).ToNullable();
            else if (prop.PropertyType == typeof(int))
                val = ResultSet.GetInt32(column);
            else if (prop.PropertyType == typeof(int?))
                val = ResultSet.GetSqlInt32(column).ToNullable();
            else if (prop.PropertyType == typeof(double))
                val = ResultSet.GetDouble(column);
            else if (prop.PropertyType == typeof(double?))
                val = ResultSet.GetSqlDouble(column).ToNullable();
            else if (prop.PropertyType == typeof(DateTime))
                val = ResultSet.GetDateTime(column);
            else if (prop.PropertyType == typeof(DateTime?))
                val = ResultSet.GetSqlDateTime(column).ToNullable();
            else if (prop.PropertyType == typeof(string))
                val = ResultSet.GetString(column);
            else
                throw new ArgumentException("Invalid property type {0}".Expand(prop.PropertyType.ToString()));

            prop.SetValue(record, val, null);
        }

        return record;


    }

In C# from time to time the issue creeps out. Usually I get an object value and then I have to call "real" function for it. Something like this:

if (type==typeof(byte))
  val = rs.GetByte(col);
else if (type==typeof(int))
  val = rs.GetInt32(col);
...

or

if (type==typeof(byte))
  Call((byte)val);
else if (type==typeof(int))
  Call((int)val);
...

I can see a textual pattern here, but I didn't come up with solution which would deal once for good with all the dirty work.

How do you deal it? You receive the object value and you have to either set it or pass it but not as an object but concrete type (PODs, Nullable of PODs and string) and...?

Edits

Complete example (this one is the cause of the question):

    protected IRecord ReadRecord()
    {
        if (!ResultSet.Read())
            return null;

        IRecord record = CreateIRecord();

        var type = record.GetType();
        int column = -1;

        foreach (var prop in type.GetProperties())
        {
            ++column;
            object val;

            if (prop.PropertyType == typeof(byte))
                val = ResultSet.GetByte(column);
            else if (prop.PropertyType == typeof(byte?))
                val = ResultSet.GetSqlByte(column).ToNullable();
            else if (prop.PropertyType == typeof(int))
                val = ResultSet.GetInt32(column);
            else if (prop.PropertyType == typeof(int?))
                val = ResultSet.GetSqlInt32(column).ToNullable();
            else if (prop.PropertyType == typeof(double))
                val = ResultSet.GetDouble(column);
            else if (prop.PropertyType == typeof(double?))
                val = ResultSet.GetSqlDouble(column).ToNullable();
            else if (prop.PropertyType == typeof(DateTime))
                val = ResultSet.GetDateTime(column);
            else if (prop.PropertyType == typeof(DateTime?))
                val = ResultSet.GetSqlDateTime(column).ToNullable();
            else if (prop.PropertyType == typeof(string))
                val = ResultSet.GetString(column);
            else
                throw new ArgumentException("Invalid property type {0}".Expand(prop.PropertyType.ToString()));

            prop.SetValue(record, val, null);
        }

        return record;


    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘东忘西忘不掉你 2024-11-12 19:19:49

您可以使用策略模式。只需将每种类型的策略放入哈希表中,然后就不需要开关了。但是,每个策略都需要一个类。如果您有复杂的逻辑,它尤其有用。

如果逻辑相当简单,您也可以使用包含委托的哈希表。

//pseudo code
handlers.put(typeof(int), delegate(object value) { return something.GetInt32(value); });

//like this
var handler = handlers[type];
handler.Invoke(val);

You could use a strategy pattern. Just put the strategies for each type in a hashtable and then you don't need the switches. However, you'll need one class per strategy. It is especially useful if you have complex logic.

If the logic is rather simple you could also use a Hashtable containing delegates.

//pseudo code
handlers.put(typeof(int), delegate(object value) { return something.GetInt32(value); });

//like this
var handler = handlers[type];
handler.Invoke(val);
木格 2024-11-12 19:19:49

您可以使用 is 运算符对其进行一些清理:

if (MyType is BaseType)...

You could clean it up a bit using the is operator:

if (MyType is BaseType)...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文