在 F# 中调用另一个 dll 的类型提供程序 [英] Type provider calling another dll in F#

查看:23
本文介绍了在 F# 中调用另一个 dll 的类型提供程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在为提供的类型构建内部表示时,我在引用中间接调用了我的类型的内部表示,另一个 dll,我可以修改其代码.

In the construction of the internal representation for a provided type, I call indirectly in the quotation for the internal representation of my type, another dll, whose code I can modify.

目前,当我使用类型提供程序时,告诉我它找不到这样的 dll:

Currently, when I consume the type provider, tells me it can't find such dll:

无法加载文件或程序集 xxxx 或其依赖项之一"

"Could not load file or Assembly xxxx or one of its dependency"

但是,当我使用 Process Explorer 检查 VS 时,我可以看到 dll XXX 已加载...有什么办法可以让引号中的代码接受来自外部 dll 的代码?

When I inspect VS using Process Explorer, though, I can see the dll XXX loaded... Are there anything to do to have the code in quotations accept code from outside dll ?

** 更新 **

我尝试了一个简化的示例,似乎可以在没有任何特殊操作的情况下调用此类外部 dll.就我而言,所有依赖的 dll XXX 都已加载,当我调试 devenv.exe 本身时,我在进程资源管理器以及模块窗口中看到它们....

I tried with a simplified example, and it seems that it is possible to call such outside dll without any special thing to do. In my case, all the dll XXX depends on are loaded, I see them in Process explorer as well as in the modules windows when I debug devenv.exe itself....

我不知道该往哪里看.这是内部异常.

I have no idea where to look to. Here is the inner exception.

** 更新 **

如果我在此路径之一中复制 xxx dll 及其依赖项,则编译器可以正常工作.我仍然想知道什么可以触发 devenv.exe 正确显示它们已加载但无法访问.

If I copy the xxx dll and its dependencies in one of this path, the compiler works fine. I still wonder what can trigger devenv.exe to correctly show them loaded but not accessible.

=== Pre-bind state information ===
LOG: User = xxxAdministrator
LOG: DisplayName = bloombergapi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:UsersAdministratorAppDataLocalMicrosoftVisualStudio11.0devenv.exe.config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:WindowsMicrosoft.NETFrameworkv4.0.30319configmachine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/bloombergapi/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/PublicAssemblies/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/PublicAssemblies/bloombergapi/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/PrivateAssemblies/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/PrivateAssemblies/bloombergapi/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TemplateProviders/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TemplateProviders/bloombergapi/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Platform/Debugger/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Platform/Debugger/bloombergapi/bloombergapi.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/PrivateAssemblies/DataCollectors/bloombergapi.DLL.

...

答案

似乎不可能调用一个函数,该函数将另一个库中的类型作为参数.联合类型有效,但不是正确的类型......如下图所示

It seems impossible to call a function that takes as an argument a Type from another library. A union type works, but not a type proper... This is illustrated below

--Library.dll

--Library.dll

namespace Library

module SampleModule = 
     type LocalUnion = | LocalUnion  of int

     type Localtype() = 
        member x.value = 2

--LibraryTP.dll

--LibraryTP.dll

namespace LibraryTP

module Module =
   open System.Reflection
   open Samples.FSharp.ProvidedTypes
   open FSharpx.TypeProviders.DSL
   open Microsoft.FSharp.Core.CompilerServices

   let f a = 
     Library.SampleModule.sampleFunction a a 

   let g (a:Library.SampleModule.LocalUnion) = 
      let (Library.SampleModule.LocalUnion(v)) = a
      v

   let ftype (a:Library.SampleModule.Localtype) = 
        a.value

   let createTP ns =
       erasedType<obj> (Assembly.GetExecutingAssembly()) ns "Outside"
       |> staticParameter "file"
          (fun typeName (parameterValues:string) ->
               erasedType<obj> (Assembly.GetExecutingAssembly()) ns typeName
               |+!> (   provideProperty 
                           "test"                             //OK
                           typeof<float>                   
                           (fun args -> <@@  g ( f 2 ) @@>)      
                         |> makePropertyStatic
                     )
               |+!> (   provideProperty 
                           "test2"                             //KO
                           typeof<int>                   
                           (fun args -> <@@ ftype ( Library.SampleModule.Localtype())  @@>)   
                        |> makePropertyStatic   
                     )
                  )

   [<TypeProvider>]
   type public CustomTypeProvider(cfg:TypeProviderConfig) as this =
      inherit TypeProviderForNamespaces()

      do this.AddNamespace("TP", [createTP "TP"])

   [<TypeProviderAssembly>]
   do()

--Program.fs

--Program.fs

   type sampleValue = TP.Outside<""> 

   [<EntryPoint>] 
   let main(args) = 
      let t = sampleValue.Test        //OK
      let tt = sampleValue.Test2      //KO 

推荐答案

您的程序集可能会加载到不同的 绑定上下文.当引用被反序列化时,它可能会尝试将程序集加载到一个绑定上下文,即使程序集已经加载到另一个上下文,该尝试也可能会失败.作为类型提供程序设计时程序集中的解决方法,您可以将处理程序添加到 AssemblyResolve 事件并尝试在已加载程序集列表中查找目标程序集.

Your assembly may be loaded into the different binding context. When quotation is deserialized it may try to load the assembly to the one binding context and this attempt may fail even if assembly was already loaded to another context. As workaround in your type provider design time assembly you can add handler to the AssemblyResolve event and try to find target assembly in the list of already loaded assemblies.

    do System.AppDomain.CurrentDomain.add_AssemblyResolve(fun _ args ->
        let name = System.Reflection.AssemblyName(args.Name)
        let existingAssembly = 
            System.AppDomain.CurrentDomain.GetAssemblies()
            |> Seq.tryFind(fun a -> System.Reflection.AssemblyName.ReferenceMatchesDefinition(name, a.GetName()))
        match existingAssembly with
        | Some a -> a
        | None -> null
        )

这篇关于在 F# 中调用另一个 dll 的类型提供程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆