简体   繁体   中英

Can not get instance of type derived in F# library correctly

I'm having a problem in my project with using types from F# in C# library.

I have an application which basically consists of the following main parts:

  • core library (.NET Standard 2.1);
  • WPF client.

The core library contains all the platform independent logic and view-models and can be used in any kind of UI clients. The application is designed to be extensible and can plug extensions dynamically before UI is loaded. For now it's just loading DLL's from the specific folder via Assembly.LoadFrom . The only requirement for the dll to be recognized as an extension is to expose special class that derives from the Module or Extension classes that are defined in core library. And it's working perfectly when loading assemblies written in C#. But I got struggle with very strange behavior when trying to use extension that is written in F#. Let's say I have an interface IRecognitionProcessor that is defined in my core library. Here are some of it's members:

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

    bool ContainsFace(Bitmap bitmap);

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

In my new extension that provides the custom recognition based on EmguCV library for .NET I have a descendant to IRecognitionProcessor that in result will be extracted and stored in special container. The extension is written in F#, as I've mentioned before. That's a brief example of the implementation:

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

It is loaded correctly without any errors, and all the assemblies that come along with it also loaded normally. The problem arise when I'm fetching all the processors from my attached extensions. Here is the simplified representation of code that describes module and how it provides the processor:

type EmguRecognitionModule() = 
    inherit RecognitionModule()

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

When new module is loaded - it's processor being extracted and stored in storage. Both step with instantiating module via Activator.CreateInstance and fetching it's processor via GetRecognitionProcessor method works fine. This is the method that populates one of my view-model's collection of processors:

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();
}

Pretty simple, though it works bad when processors come from F# library. Even if there are processors, the SelectedProcessor property will not be assigned to the first processor at all, it's still null . When I put a breakpoint and tried to observe the properties of the processors stored in the collection - inspection shows none of properties. Here is the link to example of property inspection I've made in JetBrains Rider . But when I'm using Evaluate window, I can access all the properties and methods of the object and IntelliSense works perfectly. Link to image with example of evaluation . This whole situation makes me feel dumb. Just faced this problem first time. Previously, all my attempts to use types defined in F# libraries succeeded. But this one is an exception. I see that using type derived from the abstract one works nice. But type that implements the interface somehow doesn't.

After playing with F# project settings and recreating the project from scratch I finally managed to resolve the problem - though the origin of the problem is still a mystery.
But still there is a problem with Rider's property inspector that shows only those members that are declared in the interface descendant directly. I'll check out JetBrains support if there are similar issues already posted.

upd
Seems that DisplayMemberPath of the CheckBox (specified in XAML ) also couldn't resolve the implemented properties from the instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM