1

我试图在 .NET 中获取 MailMessage 以返回 MIME 消息的字符串,但这在传递的类中没有提供。关于如何创建 C# 扩展方法来猴子修补类以提供功能还有另一个很好的答案。我正在尝试使用类型扩展将其移植到 F#,但我对如何提供参数感到困惑(特别是考虑到其中一个参数是 F# 关键字)。

非常感谢您解释如何通过答案正确完成此操作。

这是我到目前为止所得到的(当然,目前还不能编译):

open System.Net.Mail

module MailExtension =
    type MailMessage with 
        member this.toEml mail =
            let stream = new MemoryStream();
            let mailWriterType = mail.GetType().Assembly.GetType("System.Net.Mail.MailWriter");
            let mailWriter = Activator.CreateInstance(
                                type: mailWriterType,
                                bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic,
                                binder: null,
                                args: new object[] { stream },
                                culture: null,
                                activationAttributes: null)

            mail.GetType().InvokeMember(
                                name: "Send",
                                invokeAttr: BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
                                binder: null,
                                target: mail,
                                args: new object[] { mailWriter, true, true });


            Encoding.UTF8.GetString(stream.ToArray());
4

1 回答 1

3

以下是有关如何将 C# 转换为 F# 的一些提示:

  • 这 ; 不再需要
  • 对 IDisposables 使用“使用”而不是“让”
  • 对于数组使用 [| 成员1,成员2 |]
  • 对于命名参数,使用 name=value
  • 将关键字包装在名称中的名称中
  • 位运算符是 ||| 和 &&&
  • 使用实例名称而不是参数

编译的代码:

open System
open System.IO
open System.Net.Mail
open System.Reflection
open System.Text

module MailExtension =
    type MailMessage with 
        member this.toEml () =
            use stream = new MemoryStream()
            let mailWriterType = this.GetType().Assembly.GetType("System.Net.Mail.MailWriter")
            let mailWriter = Activator.CreateInstance(
                                ``type`` = mailWriterType,
                                bindingAttr = (BindingFlags.Instance ||| BindingFlags.NonPublic),
                                binder = null,
                                args = [| stream |],
                                culture = null,
                                activationAttributes = null)

            this.GetType().InvokeMember(
                                name = "Send",
                                invokeAttr = (BindingFlags.Instance ||| BindingFlags.NonPublic ||| BindingFlags.InvokeMethod),
                                binder = null,
                                target = this,
                                args = [| mailWriter, true, true |])


            Encoding.UTF8.GetString(stream.ToArray())

然后使用:

open MailExtension
let m = new MailMessage()
m.toEml () |> ignore
于 2018-01-29T10:42:36.643 回答