Не удается правильно получить экземпляр типа, выведенного из библиотеки F # - PullRequest
1 голос
/ 01 декабря 2019

У меня проблема в моем проекте с использованием типов из F # в библиотеке C #.

У меня есть приложение, которое в основном состоит из следующих основных частей:

  • coreбиблиотека (.NET Standard 2.1);
  • Клиент WPF.

Библиотека core содержит все независимые от платформы логику и модели представления и может использоваться влюбой вид клиентов пользовательского интерфейса. Приложение разработано для расширения и может динамически подключать расширения перед загрузкой пользовательского интерфейса. На данный момент он просто загружает DLL из определенной папки через Assembly.LoadFrom . Единственное требование для того, чтобы dll был распознан как расширение, - это предоставить специальный класс, производный от Module или Extension классов, определенных в ядро библиотека. И он отлично работает при загрузке сборок, написанных на C #. Но я столкнулся с очень странным поведением, когда пытался использовать расширение, написанное на F #. Допустим, у меня есть интерфейс IRecognitionProcessor , который определен в моей основной библиотеке. Вот некоторые из его членов:

public interface IRecognitionProcessor
{
    string Name { get; }
    string Description { get; }

    bool ContainsFace(Bitmap bitmap);

    FaceDetail[] ExtractDetails(Bitmap bitmap);
    /* more members goes here */
}

В моем новом расширении, обеспечивающем пользовательское распознавание на основе EmguCV библиотеки для .NET, у меня есть потомок IRecognitionProcessor что в результате будет извлечено и сохранено в специальном контейнере. Расширение написано на F #, как я уже упоминал ранее. Вот краткий пример реализации:

type EmguFaceRecognition() =
interface IRecognitionProcessor with
    member this.Name : string = "EmguCV"
    member this.Description : string = "EmguCV face recognition processor"

    member this.ContainsFace (bitmap : Bitmap) : bool =
        //code goes here

    member this.ExtractDetails (bitmap : Bitmap) : FaceDetail array =
        //code goes here

    // other implementations

Он загружается правильно без каких-либо ошибок, и все сборки, которые идут вместе с ним, также загружаются нормально. Проблема возникает, когда я выбираю все процессоры из моих подключенных расширений. Вот упрощенное представление кода, который описывает модуль и как он предоставляет процессор:

type EmguRecognitionModule() = 
    inherit RecognitionModule()

override this.GetRecognitionProcessor() : IRecognitionProcessor =
    new EmguFaceRecognition() :> IRecognitionProcessor
// more code goes here

Когда загружается новый модуль - его процессор извлекается и сохраняется в хранилище. Оба шага с созданием экземпляра модуля с помощью Activator.CreateInstance и извлечения его процессора с помощью GetRecognitionProcessor метода работают нормально. Это метод, который заполняет один из наборов процессоров моей модели представления:

public void PopulateRecognitionProcessors(IEnumerable<IRecognitionProcessor> processors, AccessToken accessToken)
{
    if (accessToken != _parentAccessToken)
        throw new AccessViolationException("Attempt to set recognition processors from outside of the parent"); 

    _recognitionProcessors.Clear();
    _recognitionProcessors.AddRange(processors);

    SelectedProcessor = _recognitionProcessors.FirstOrDefault();
}

Довольно простой, хотя он плохо работает, когда процессоры приходят из библиотеки F #. Даже если есть процессоры, свойство SelectedProcessor не будет назначено первому процессору вообще, оно все равно будет null . Когда я поставил точку останова и попытался наблюдать свойства процессоров, хранящихся в коллекции - проверка не показала ни одно из свойств. Вот ссылка на пример проверки свойств, которую я сделал в JetBrains Rider . Но когда я использую окно Evaluate , я могу получить доступ ко всем свойствам и методам объекта, и IntelliSense работает отлично. Ссылка на изображение с примером оценки . Вся эта ситуация заставляет меня чувствовать себя глупым. Просто столкнулся с этой проблемой впервые. Ранее все мои попытки использовать типы, определенные в библиотеках F #, увенчались успехом. Но это исключение. Я вижу, что использование типа, производного от абстрактного, работает хорошо. Но типа, который реализует интерфейс, как-то нет.

...