2012-04-27 5 views
4

При построении внутреннего представления для предоставленного типа я косвенно вызываю в цитате для внутреннего представления моего типа, другую dll, код которой я могу изменить.Введите оператора, вызывающего другую dll в F #

В настоящее время, когда я потребляю провайдера типа, говорит мне, что не может найти такую ​​DLL:

«Не удалось загрузить файл или сборку хххх или один из его зависимостей»

Когда я инспектировать VS с помощью Process Explorer, однако, я вижу, что DLL XXX загружена ... Есть ли что-нибудь сделать, чтобы код в котировках принимал код из внешней DLL?

** Обновление **

Я попытался с упрощенным, например, и, кажется, что можно назвать такой DLL снаружи без какого-либо специального, что нужно сделать. В моем случае все DLL-файлы XXX зависят от загруженных, я вижу их в Process explorer, а также в окнах модулей, когда я сам отлаживаю сам файл devenv.exe.

Я понятия не имею, где искать. Вот внутреннее исключение.

** Обновление **

Если я копирую ххх DLL и его зависимости в одном из этого пути, компилятор работает отлично. Я все еще удивляюсь, что может вызвать файл devenv.exe, чтобы правильно показать, что они загружены, но недоступны.

=== Pre-bind state information === 
LOG: User = xxx\Administrator 
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:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\11.0\devenv.exe.config 
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.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. 

...

ОТВЕТ

Это кажется невозможным, чтобы вызвать функцию, которая принимает в качестве аргумента типа из другой библиотеки. тип союз работает, но не тип собственно ... Это проиллюстрировано ниже

--Library.dll

namespace Library 

module SampleModule = 
    type LocalUnion = | LocalUnion of int 

    type Localtype() = 
     member x.value = 2 

--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

type sampleValue = TP.Outside<""> 

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

Глупый вопрос Я предполагаю, но вы уверены, что все зависимости dll XXX также загружаются в память? –

ответ

10

Ваша сборка может быть загружена в разные binding context. Когда котировка десериализована, она может попытаться загрузить сборку в один контекст привязки, и эта попытка может потерпеть неудачу, даже если сборка уже загружена в другой контекст. В качестве обходного пути в сборке времени разработки вашего типа вы можете добавить обработчик к AssemblyResolve event и попытаться найти целевую сборку в списке уже загруженных сборок.

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 
     ) 
+0

Вот и все. большое спасибо за предложение, я бы не подумал об этом за миллион лет. вы не так уж плохи с этими новыми машинами. – nicolas

+0

Когда я это пробовал, необходимые сборки были (по-видимому) не загружены, поэтому я расширил эту идею, чтобы ResolveEventHandler также искал папку «пакеты» в родительских каталогах и искал соответствующую DLL. –

Смежные вопросы