简体   繁体   English

无法正确获取 F# 库中派生类型的实例

[英]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.我的项目在 C# 库中使用 F# 的类型时遇到问题。

I have an application which basically consists of the following main parts:我有一个基本上由以下主要部分组成的应用程序:

  • core library (.NET Standard 2.1);核心库(.NET Standard 2.1);
  • WPF client. WPF 客户端。

The core library contains all the platform independent logic and view-models and can be used in any kind of UI clients.核心库包含所有与平台无关的逻辑和视图模型,可用于任何类型的 UI 客户端。 The application is designed to be extensible and can plug extensions dynamically before UI is loaded.该应用程序被设计为可扩展的,并且可以在加载 UI 之前动态插入扩展。 For now it's just loading DLL's from the specific folder via Assembly.LoadFrom .现在它只是通过Assembly.LoadFrom从特定文件夹加载DLL 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.dll识别为扩展的唯一要求是公开派生自核心库中定义的模块扩展类的特殊类。 And it's working perfectly when loading assemblies written in C#.在加载用 C# 编写的程序集时,它工作得很好。 But I got struggle with very strange behavior when trying to use extension that is written in F#.但是当我尝试使用用 F# 编写的扩展时,我遇到了非常奇怪的行为。 Let's say I have an interface IRecognitionProcessor that is defined in my core library.假设我有一个在我的核心库中定义的接口IRecognitionProcessor 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.在我为 .NET 提供基于EmguCV库的自定义识别的新扩展中,我有一个IRecognitionProcessor的后代,结果将被提取并存储在特殊容器中。 The extension is written in F#, as I've mentioned before.正如我之前提到的,该扩展是用 F# 编写的。 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.通过Activator.CreateInstance实例化模块和通过GetRecognitionProcessor方法获取它的处理器这两个步骤都可以正常工作。 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.非常简单,尽管当处理器来自 F# 库时效果不佳。 Even if there are processors, the SelectedProcessor property will not be assigned to the first processor at all, it's still null .即使有处理器, SelectedProcessor属性也根本不会分配给第一个处理器,它仍然是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 .这是我在 JetBrains Rider 中制作的属性检查示例的链接 But when I'm using Evaluate window, I can access all the properties and methods of the object and IntelliSense works perfectly.但是当我使用Evaluate窗口时,我可以访问对象的所有属性和方法,并且 IntelliSense 可以完美运行。 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.以前,我使用 F# 库中定义的类型的所有尝试都成功了。 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.在使用 F# 项目设置并从头开始重新创建项目后,我终于设法解决了这个问题——尽管问题的根源仍然是个谜。
But still there is a problem with Rider's property inspector that shows only those members that are declared in the interface descendant directly.但是 Rider 的属性检查器仍然存在问题,它只显示直接在接口后代中声明的那些成员。 I'll check out JetBrains support if there are similar issues already posted.如果已经发布了类似的问题,我会查看 JetBrains 支持。

upd更新
Seems that DisplayMemberPath of the CheckBox (specified in XAML ) also couldn't resolve the implemented properties from the instance.似乎CheckBoxDisplayMemberPath (在XAML中指定)也无法从实例解析已实现的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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