В F # может ли тип записи быть общедоступным, когда он находится в модуле внутри пространства имен?

#f#

#f#

Вопрос:

В F # тип записи, размещенный непосредственно в пространстве имен, будет скомпилирован как тип класса для C #.

 e.g., 
namespace MyNameSpace
type MyType  = { Name: string; Content: string; Text: string }
  

C # будет рассматривать MyType как статический общедоступный класс.

Но как C # видит MyType, когда он находится в модуле внутри пространства имен?

 e.g.,
 namespace MyNameSpace
 module MyModule
    type MyType  = { Name: string; Content: string; Text: string }
  

Если он является закрытым для MyModule, может ли он быть общедоступным для C #?

(Я не смог найти этот ответ в Google : ( )

TIA

Ответ №1:

Модуль F # компилируется как класс. Если у вас есть объявление типа внутри модуля, оно будет скомпилировано как вложенный класс. В вашем примере MyNameSpace.MyModule.MyType MyNameSpace часть является пространством имен, но MyModule (а также MyType ) являются классами.

В C # доступ к вложенным классам осуществляется с помощью . , но на уровне CLR доступ к вложенному классу осуществляется с помощью , поэтому, если вы хотите получить доступ, MyType например, с помощью Type.GetType , вам нужно использовать:

 System.Type.GetType("MyNameSpace.MyModule MyType")
  

Обратите внимание, что это не работает в F # Interactive, который добавляет другое имя в пространство имен, но это работает в скомпилированном коде. Я не уверен, как это работает DataTemplate в WPF, но, возможно, вам нужно указать тип, используя формат CLR с в имени.

Ответ №2:

По умолчанию я полагаю, что все члены модуля будут следовать одной и той же общедоступной статической форме объявления. Результатом компиляции вашего примера здесь является легко доступный класс MyType из C#:

 static void Main(string[] args)
{
    var foo = new MyNameSpace.MyModule.MyType("x", "b", "c");
}
  

Чтобы принудительно контролировать доступ к элементу модуля, вам нужно немного изменить объявление:

 module MySecrets =
    type private SecretType = { Password: string }
  

РЕДАКТИРОВАТЬ: Ага, нашел соответствующую страницу:https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/access-control

Комментарии:

1. Я тоже так думал. Однако, когда MyType используется в DataTemplate WPF / C #, as DataType=»{x:Type vm:MyType}» работает с vm, являющимся указателем на пространство имен. Но, тип данных=»{x: Тип виртуальной машины:MyModule. MyType}» в среде CLR постоянно происходит сбой, сообщающий, что он не может найти MyType. Возможно, это связано с WPF CLR??? В любом случае, кажется, что он должен быть в пространстве имен.

2. Записи могут помещаться в модули и использоваться клиентами C #. Имя модуля является частью определенного пути при доступе к записи. Пример: откройте my_namespace_path.my_module.

3. @ScottNimrod Возможно, это так для клиентов C # — не так сильно для wpf / xaml. Кажется, что среда CLR просматривает только записи F # непосредственно в пространстве имен. Я не смог успешно разместить запись в модуле, который сам находится в пространстве имен : (

4. Я создаю мобильные приложения, используя F # с Xamarin. Forms, который также является XAML. Я думаю, что у вас другая проблема, с которой вы сталкиваетесь.

5. Рассматривали ли вы возможность использования статического импорта имени класса в вашем коде за файлами? Пример: использование статического mynamespece.mymodule