为什么我们没有标记[Serializable]的类,同时继承MarshalByRefObject?

时间:2014-04-23 09:05:54

标签: c# .net .net-remoting

我知道这听起来很愚蠢,但我只是好奇。我的讲师问了这个问题,我们一无所知。 :d

2 个答案:

答案 0 :(得分:6)

你的讲师不对。

foreach(var type in typeof(Uri).Assembly.GetTypes())
{
    if (type.IsAbstract) continue;
    if (!Attribute.IsDefined(type, typeof(SerializableAttribute))) continue;
    if (!typeof(MarshalByRefObject).IsAssignableFrom(type)) continue;
    Console.WriteLine(type.FullName);
}

显示(并注意我只在这里查看单个程序集):

System.Media.SoundPlayer
System.Net.FileWebRequest
System.Net.FileWebResponse
System.Net.HttpWebRequest
System.Net.HttpWebResponse
System.Diagnostics.EventLogEntry

果然,http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx显示:

[SerializableAttribute]
public class HttpWebRequest : WebRequest, 
    ISerializable

还注意到:

[SerializableAttribute]
public abstract class WebRequest : MarshalByRefObject, 
    ISerializable

对于mscorlib(typeof(object)),我们得到:

System.IO.Stream+SyncStream
System.IO.DirectoryInfo
System.IO.FileInfo
System.IO.MemoryStream
System.IO.TextReader+SyncTextReader
System.IO.StreamReader
System.IO.TextWriter+SyncTextWriter
System.IO.StreamWriter
System.IO.StringReader
System.IO.StringWriter
System.IO.Stream+NullStream
System.IO.TextReader+NullTextReader
System.IO.TextWriter+NullTextWriter

我怀疑那个具体反例。

我怀疑你的讲师想到了远程处理,即我们希望 能够远程作为代理/存根对,或者通过序列化。但是,这是无效的。

  • [Serializable]也仅用于远程处理之外的序列化目的
  • 远程类可以(并且通常是)单独使用并独立于远程处理
  • 远程停止;告诉他们停止教远程,请

或者,考虑:

使用远程处理时,MarshalByRefObject表示该对象应由代理/存根进行远程处理 - 否则,该对象需要可序列化,因此需要[Serializable]。然而,情况恰恰相反:[Serializable] 意味着"按价值编组" (简单地说:缺少MarshalByRefObject意味着"按价值编组")。类型可以通过代理/存根进行序列化和远程处理。这里没有冲突。

答案 1 :(得分:0)

MarshalByRefObject已标记为Serializable,因此这看起来有点奇怪。

但是,这更多是关于逻辑上使用您拥有的工具。由于MarshalByRefObject实际上是使用代理访问的,因此当您使用代理时,它们不具有要序列化的本地状态。这是MarshalByRefObject的重点。当您使用序列化时,您将转移(或保存)状态 - 当通过引用进行编组时,您只需要传输对象的引用。因此序列化是一个副本,而ref的编组仍然引用同一个对象,甚至是跨应用程序域边界。

现在,据我所知,实际上没有检查以确保该对象不可序列化 - 但是,实际上,当它从应用程序域外部使用时,没有什么可以序列化的。