Управление ссылками F# при компиляции из скрипта fsx

Мне нужно взаимодействовать с SharePoint (локально), и я решил попробовать F#. Это или должно быть достаточно просто, чтобы я сделал это только с помощью инструментов CLI.

Мне удалось взаимодействовать с сайтом и получить необходимую информацию. Я боролся с необходимой DLL, но в итоге

#if INTERACTIVE
#r @"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
#r @"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

// seems to be required
#r @"[...]\Microsoft.Online.SharePoint.Client.Tenant.dll.15.0.4615.1001\Microsoft.Online.SharePoint.Client.Tenant.dll"

#r @"[...]\SharePointPnPCoreOnline.3.8.1904\lib\net45\OfficeDevPnP.Core.dll"

#endif

работал с Fsi REPL или Fsi script.fsx, но я не могу его скомпилировать, будь то файл fs или скрипт fsx.

Мой код, скажем:

open Microsoft.SharePoint.Client;;

let main () = 
    let authnManager = OfficeDevPnP.Core.AuthenticationManager()
    printfn "%A" authnManager
    0

main()

Работа с fsi:

PS> fsi script.fsx
OfficeDevPnP.Core.AuthenticationManager #OK!

Пытаюсь скомпилировать:

PowerShell>  fsc --warn:5 -r "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" `
>>      -r "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" `
>>      -r "absolute\path\to\Microsoft.Online.SharePoint.Client.Tenant.dll.15.0.4615.1001\Microsoft.Online.SharePoint.Client.Tenant.dll" `
>>      -r "absolute\path\to\SharePointPnPCoreOnline.3.8.1904\lib\net45\OfficeDevPnP.Core.dll"  .\script.fsx
Microsoft (R) F# Compiler version 10.4.0 for F# 4.6
Copyright (c) Microsoft Corporation. All Rights Reserved.

> .\script.exe

Exception non gérée (unmanaged exception) : System.IO.FileNotFoundException: 
Impossible de charger le fichier ou l'assembly 'OfficeDevPnP.Core,
Version=3.8.1904.0, Culture=neutral, PublicKeyToken=5e633289e95c321a'
ou une de ses dépendances. Le fichier spécifié est introuvable.
   à Script.main()
   à <StartupCode$script>.$Script$fsx.main@()

Почему эта разница? Что мне не хватает? Как загрузить ссылки с помощью fsc (поскольку nuget установил довольно много переходных зависимостей)? Ими нужно управлять как с помощью fsc, так и с помощью fsi! (Если нет конкретной проблемы с OfficeDevPnP.Core.dll...)


person jgran    schedule 24.05.2019    source источник


Ответы (1)


Я думаю, что библиотеки DLL, на которые ссылается #r в F# Interactive, должны быть в порядке зависимости. Таким образом, если DLL-библиотеки SharePoint зависят от DLL-библиотеки OfficeDevPnp, то сначала необходимо сослаться на DLL-библиотеку OfficeDevPnp (ее #r строка должна стоять перед #r строками SharePoint). Вам придется сбросить интерактивный сеанс после того, как вы загрузили библиотеки DLL, чтобы повторно загрузить их в правильном порядке.

В общем, загрузка зависимостей пакетов в интерактивном F# довольно сложна. Есть несколько инструментов F#, таких как Paket. ваша жизнь немного легче. Другой вариант, если у вас уже есть проект Visual Studio с нужными вам ссылками, — использовать его для создания ссылок на пакеты для вашего файла скрипта. Вы можете прочитать файл .fsproj и сгенерировать операторы #r из ссылок, используемых в проекте. Что-то вроде этого может сработать:

#r "System.Xml"
#r "System.Xml.Linq"

open System
open System.IO
open System.Linq
open System.Xml.Linq

let inline isNotNull o = o |> isNull |> not

let private getProject path =
    Directory.EnumerateFiles(path, "*.*proj") |> Seq.head |> XDocument.Load    

let generateDlls path =
    let projectFile = getProject path
    let references =
        projectFile.Descendants <| XName.Get("HintPath", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.filter (fun reference -> reference.Value.ToLower().EndsWith(".dll"))
        |> Seq.filter (fun reference -> reference.Value.StartsWith("$") |> not)
        |> Seq.map (fun reference -> reference.Value)
    let projects =
        projectFile.Descendants <| XName.Get("ProjectReference", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.map (fun reference -> reference.Elements(XName.Get("Name", "http://schemas.microsoft.com/developer/msbuild/2003")).SingleOrDefault())
        |> Seq.filter (fun nameElement -> nameElement |> isNotNull)
        |> Seq.map (fun nameElement -> nameElement.Value)
        |> Seq.map (fun reference -> sprintf "../%s/bin/debug/%s.dll" reference reference)

    references 
    |> Seq.append projects
    |> Seq.iter (fun reference -> printfn "#r @\"%s\"" reference)
person Aaron M. Eshbach    schedule 24.05.2019