XML 序列化委托

发布于 2024-08-20 18:11:27 字数 509 浏览 7 评论 0原文

我有一个想要可序列化的类,但包含一个显然无法序列化的委托的公共实例:

<Serializable()> Class A
    Public Delegate Function TestEventHandler(ByVal myObj as CutomObject, _
                                         ByVal myObj2 as CustomObject) as Boolean

    ' does not 'want' to be serialized - cause: no parameterless constructor'
    Public TestDelegate as TestEventHandler
End Class

我使用了 ; _ 它有帮助 - 我的意思是不再向该成员抛出异常。

有没有办法让它可序列化?

I have a class that I want to be serializable but contains a public instance of delegate that, apparently can't be serialized:

<Serializable()> Class A
    Public Delegate Function TestEventHandler(ByVal myObj as CutomObject, _
                                         ByVal myObj2 as CustomObject) as Boolean

    ' does not 'want' to be serialized - cause: no parameterless constructor'
    Public TestDelegate as TestEventHandler
End Class

I used <XmlIgnore()> _ and it helped - i mean the exception is not trowed at this member anymore.

Is there a way to make it serializable however?

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

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

发布评论

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

评论(4

傲娇萝莉攻 2024-08-27 18:11:27

在委托上使用[XmlIgnore]


不,没有办法序列化委托。它会是什么样子?.NET 以外的平台会用它做什么?

Use [XmlIgnore] on the delegate.


No, there's no way to serialize a delegate. What would it even look like, and what would a platform other than .NET do with it?

寒江雪… 2024-08-27 18:11:27

您可以尝试使用 Func<> 4.0 中的代表。它们是可序列化的。

You can try using Func<> delegates in 4.0. They are serializable.

旧人哭 2024-08-27 18:11:27

你的问题是?

委托不能被序列化是完全可以理解的,因为它可以被视为“函数指针”而不是真实的数据。

您可以通过将 NonSerialized 属性应用于该委托来解决您的问题。

[Serializable]
public class Test
{
    [NonSerialized]
    public TestEventHandler TestDelegate;
}

但是,请记住,Xml 序列化需要其他属性,然后通过 BinaryFormatterSoapFormatter 类进行“常规”序列化。

使用 XmlSerialization 时,应使用 XmlIgnore 属性。
使用 XmlSerialization 时,不必将类标记为 Serialized
相反,它应该有一个默认的公共构造函数。 XmlSerialization 仅序列化具有 getter 和 setter 的公共属性。
您可以通过 控制通过 XmlSerialization 序列化对象的方式这些属性

And your question is ?

It is quite understandable that a delegate cannot be serialized, since it can be seen as a 'function pointer' rather then real data.

You can solve your problem by applying the NonSerialized attribute to that delegate.

[Serializable]
public class Test
{
    [NonSerialized]
    public TestEventHandler TestDelegate;
}

But, remember that Xml Serialization requires other attributes then 'regular' serialization through the BinaryFormatter or SoapFormatter classes.

When you use XmlSerialization, you should use the XmlIgnore attribute.
When you use XmlSerialization, you do not have to mark your class as Serializable.
Instead, it should have a default public constructor. XmlSerialization only serializes public properties, that have a getter and a setter.
You can control the way your object is serialized via XmlSerialization by these attributes.

悍妇囚夫 2024-08-27 18:11:27

您还必须将要调用的委托或方法的名称作为字符串存储在类中。

我使用它是因为我想在配置文件中配置通过 ftp 下载文件后调用什么函数,即不同的 ftp 下载配置通过调用配置的方法(委托)以不同的方式处理下载的文件。

public delegate string ProcessDownloadedFile(string filename);       

        //HACK: Cannot serialise delegates.
        public string ProcessDownloadFileMethod { get; set; }

        //HACK: Cannot serialise delegates.
        [XmlIgnore]
        public ProcessDownloadedFile ProcessFile { get; set; }

然后当您想使用委托时,在本例中是在我下载文件之后。我使用存储在序列化配置文件中的字符串创建委托。

 //Create the delegate method if it has been set.
 if (!String.IsNullOrEmpty(ftpReceive.ProcessDownloadFileMethod) && ftpReceive.ProcessFile == null)
 {
 //Create the delegate.
 Type t = typeof(FTPTransfer);
 ftpReceive.ProcessFile = (FTPTransfer.ProcessDownloadedFile) Delegate.CreateDelegate(typeof(FTPTransfer.ProcessDownloadedFile), t.GetMethod(ftpReceive.ProcessDownloadFileMethod));
 }

因此,理想情况下,您希望将要调用的函数/委托的名称存储为字符串,然后在运行时使用反射从字符串创建它。

希望这有帮助。

或者,如果要调用的方法仅存在于一个类中,您可以通过包装属性来简化它。

 //HACK: Cannot serialise delegates.
 public string ProcessDownloadFileMethod { get; set; }

 //HACK: Cannot serialise delegates.
 private ProcessDownloadedFile _processFile;
 [XmlIgnore]
 public ProcessDownloadedFile ProcessFile
 {
   get
   {
     if (_processFile == null && !String.IsNullOrEmpty(ProcessDownloadFileMethod))
     {
        Type t = this.GetType();
        this._processFile = (ProcessDownloadedFile) Delegate.CreateDelegate(typeof(ProcessDownloadedFile), t.GetMethod(this.ProcessDownloadFileMethod));

      }
      return _processFile;
    }
    set
      {
         if (value != null)
         {
            ProcessDownloadFileMethod = value.Method.Name;
         } else {
            ProcessDownloadFileMethod = null;
         }
         _processFile = value;
       }
    }

要真正使其可配置,可能需要包含用于创建委托的类/类型以及函数/方法名称。

You have to store the name of the delegate or method you want to call as a string in the class as well.

I used this as I wanted to configure what function to call after a file has been downloaded via ftp in the config file, i.e. Different ftp download configurations process the downloaded file differently by calling the configured method(delegate).

public delegate string ProcessDownloadedFile(string filename);       

        //HACK: Cannot serialise delegates.
        public string ProcessDownloadFileMethod { get; set; }

        //HACK: Cannot serialise delegates.
        [XmlIgnore]
        public ProcessDownloadedFile ProcessFile { get; set; }

Then when you want to use the delegate, in this case after I have downloaded the file. I create the delegate using the string I have stored in the serialized config file.

 //Create the delegate method if it has been set.
 if (!String.IsNullOrEmpty(ftpReceive.ProcessDownloadFileMethod) && ftpReceive.ProcessFile == null)
 {
 //Create the delegate.
 Type t = typeof(FTPTransfer);
 ftpReceive.ProcessFile = (FTPTransfer.ProcessDownloadedFile) Delegate.CreateDelegate(typeof(FTPTransfer.ProcessDownloadedFile), t.GetMethod(ftpReceive.ProcessDownloadFileMethod));
 }

So ideally you want to store the name of the function/delegate you want to call as a string, and then create it from the string at run time using reflection.

Hope this helps.

Or if the methods to call will only ever exist in the one class you could simplify it by wrapping the properties to simplify it.

 //HACK: Cannot serialise delegates.
 public string ProcessDownloadFileMethod { get; set; }

 //HACK: Cannot serialise delegates.
 private ProcessDownloadedFile _processFile;
 [XmlIgnore]
 public ProcessDownloadedFile ProcessFile
 {
   get
   {
     if (_processFile == null && !String.IsNullOrEmpty(ProcessDownloadFileMethod))
     {
        Type t = this.GetType();
        this._processFile = (ProcessDownloadedFile) Delegate.CreateDelegate(typeof(ProcessDownloadedFile), t.GetMethod(this.ProcessDownloadFileMethod));

      }
      return _processFile;
    }
    set
      {
         if (value != null)
         {
            ProcessDownloadFileMethod = value.Method.Name;
         } else {
            ProcessDownloadFileMethod = null;
         }
         _processFile = value;
       }
    }

To really make this configurable it would maybe be an idea to include the Class/Type as well as the function/method name for creating the delegate.

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