【问题标题】:Is there a way of implementing methods for particular casting?有没有办法实现特定铸造的方法?
【发布时间】:2012-12-15 14:51:08
【问题描述】:

我有几个不同的类来表示消息数据(它实现了ToString() 方法)

  • DatabaseMessage
  • Method1Message
  • Method2Message
  • 等等……

然后我有一个Message 类,它有一个代表发送者的字符串和一个代表关于消息数据类之一的字符串(来自ToString() 消息)。我创建了这个类来通过我的通信管道发送消息。

在另一端,我从字符串创建一个Message 类,并将其发送到一个特定的方法,该方法确切地知道它是哪种消息数据类型。然后我想将整个消息对象转换为能够访问特定消息数据的东西(例如DatabaseMessage 类)。

class DatabaseMessage
{
    public string ToString()
    {
        // ...
    }
}

class Message
{
    public string sender;
    public string data;

    public static Message FromString(string message)
    {
        // ...
    }
}

//...

public void Send()
{
    DatabaseMessage db_mess = new DatabaseMessage();

    Message m = new Message();
    m.sender = "me";
    m.data = db_mess.ToString();
}

public void Recieve(string message)
{
    Message m = Message.FromString(message);

    DatabaseMethod(m);
}

public void DatabaseMethod(Message m)
{
    // I want to be able to do this:
    DatabaseMessage db_mess = (DatabaseMessage)m;

    //...
}

如何实现这一点?

希望这是有道理的。

【问题讨论】:

  • 您在寻找object serialization吗?
  • 也许DatabaseMessageMethod1MessageMethod2Message 类都应该将Message 类作为它们的基类?像这样:class DatabaseMessage : Message { /* ... */ }
  • 但是我如何处理从带有发送者和数据字符串的消息到具有大量参数/字段的 DatabaseMessage 的转换......当我需要转换时,处理这个的代码是什么将数据字符串放入DatabaseMessage。

标签: c# oop casting


【解决方案1】:

据我了解,您需要的是接口或扩展特定类。

如果将 Message 创建为接口,则可以定义实现它的任何东西都必须具有特定的方法。

然后要得到你想要的类型,你可以使用这样的东西:

if (myMessage.GetType() == typeof(DatabaseMessage))
{
DatabaseMessage myDatabaseMessage = (DatabaseMessage)myMessage;

//etc...

}

但是,如果您使用过接口,您甚至不需要关心类型,因为只要它们使用相同的接口,无论对象类型如何,这些方法都可以工作。

【讨论】:

  • 为什么用myMessage.GetType() == typeof(DatabaseMessage)检查类型而不是使用C#的isas关键字?如果myMessage 是比DatabaseMessage 派生的运行时类型更多,例如SpecialDatabaseMessage(派生自DatabaseMessage),则会有所不同。
  • 我要在哪里放置铸造代码!因为在某些时候我需要将字符串转换为 DatabaseMessage 对象(我可以这样做 - 我只是不知道将代码放在哪里)。
  • 好的。如果myMessage 的运行时类型是DatabaseMessage 或派生自(或在DatabaseMessage 是接口的情况下实现)DatabaseMessage,则表达式myMessage is DatabaseMessage 将返回trueas 类似,可以这样使用:var myDatabaseMessage = myMessage as DatabaseMessage; if (myDatabaseMessage != null) { /* your "etc..." */ }
  • 但是 myMessage 不是 DatabaseMessage,一旦它通过了 com 管道,它是 Message...这就是问题所在!
【解决方案2】:

我不会进入你的设计,你为什么需要这样做。

为了隐式或显式转换类型,您需要执行名为 Conversion operator overloading 的操作。

通过覆盖这些运算符,您可以分配不同类型的变量,并调用适当的方法进行转换。 (当然,当您将实现的重载方法支持转换类型时)。

    public static explicit operator DatabaseMessage (Message m)  
    {
        DatabaseMessage dm = new ...
        // conversion stuff

        return dm; // return the new DatabaseMessage after conversion
    }

希望这会有所帮助。 奥菲尔。

【讨论】:

    【解决方案3】:

    检查 typeof 类实例将要求您在每次引入新消息类型时更改方法代码 - 违反 Open/Close Principle

    我提出了另一种方法,使用对象实例的序列化(XmlSerializer 或 DatacontractSerializer)作为传输机制,然后使用多态对消息执行操作。这样,当包含一个新的消息类型时,就会引入一个新的类并重写虚方法,因此不违反打开关闭原则。

    因此,发送序列化到 Xml、传输和反序列化,然后在反序列化对象上调用 peformWorkOnMessage() 方法..

    这行得通吗?

    【讨论】:

      【解决方案4】:

      好的,看看你对此有何看法。

      你的问题是你不能这样做:

      DatabaseMessage db_mess = (DatabaseMessage)m;
      

      ...因为m 不是DatabaseMessage,而是Message。然而,据我了解,m.data 是一个字符串,它代表一个“序列化”DatabaseMessage,那么您能否在其他 Message 类型中继续您的 MessageType.FromString() 模式并执行此操作?

      DatabaseMessage db_mess = DatabaseMessage.FromString(m.data);
      

      如果问题更多的是如何判断Message 包含在m.data 中,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-12
        • 2016-07-18
        • 1970-01-01
        • 2022-08-15
        • 2011-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多