По некоторым причинам принятый ответ предлагает использовать отражение, чтобы получить метод расширения типа F #. Поскольку имя скомпилированного метода отличается в разных версиях F # и может различаться в зависимости от аргументов, встраивания и других проблем, связанных с именами, я бы предпочел вместо этого использовать CompiledNameAttribute
, что намного проще и сочетается с легко с C #. Кроме того, не нужно никаких размышлений (а также проблем с производительностью и безопасностью типов).
Предположим, у вас есть это в F #:
namespace Foo.Bar
module StringExt =
type System.String with
static member ToInteger s = System.Int64.Parse(s)
Вы не сможете вызвать это напрямую, и скомпилированная версия будет выглядеть так (в зависимости от того, есть ли перегрузки):
namespace Foo.Bar
{
using Microsoft.FSharp.Core;
using System;
[CompilationMapping(SourceConstructFlags.Module)]
public static class StringExt
{
public static long String.ToInteger.Static(string s) =>
long.Parse(s);
}
}
Если вы не используете отражение, вы не сможете получить доступ к методу String.ToInteger.Static
. Тем не менее, простой метод декорирования с CompiledNameAttribute
решает эту проблему:
namespace Foo.Bar
module StringExt =
type System.String with
[<CompiledName("ToInteger")>]
static member ToInteger s = System.Int64.Parse(s)
Теперь скомпилированный метод в Reflector выглядит следующим образом, отметьте изменение в скомпилированном имени:
namespace Foo.Bar
{
using Microsoft.FSharp.Core;
using System;
[CompilationMapping(SourceConstructFlags.Module)]
public static class StringExt
{
[CompilationSourceName("ToInteger")]
public static long ToInteger(string s) =>
long.Parse(s);
}
}
Вы все еще можете использовать этот метод так же, как вы привыкли в F # (как String.ToInteger
в данном случае). Но что более важно, теперь вы можете использовать этот метод без отражения или других хитростей из C #:
var int x = Foo.Bar.StringExt.ToInteger("123");
И, конечно, вы можете упростить свою жизнь, добавив псевдоним типа в C # для модуля Foo.Bar.StringExt
:
using Ext = Foo.Bar.StringExt;
....
var int x = Ext.ToInteger("123");
Это не то же самое, что метод расширения, и украшение статического члена атрибутом System.Runtime.CompilerServices.Extension
игнорируется. Это просто простой способ использовать расширения типа из других языков .NET. Если вы хотите, чтобы «подлинный» метод расширения действовал на тип, используйте синтаксис let
из других ответов здесь.