FSharp.Interop.Dynamic
6.0.0
dotnet add package FSharp.Interop.Dynamic --version 6.0.0
NuGet\Install-Package FSharp.Interop.Dynamic -Version 6.0.0
<PackageReference Include="FSharp.Interop.Dynamic" Version="6.0.0" />
<PackageVersion Include="FSharp.Interop.Dynamic" Version="6.0.0" />
<PackageReference Include="FSharp.Interop.Dynamic" />
paket add FSharp.Interop.Dynamic --version 6.0.0
#r "nuget: FSharp.Interop.Dynamic, 6.0.0"
#:package FSharp.Interop.Dynamic@6.0.0
#addin nuget:?package=FSharp.Interop.Dynamic&version=6.0.0
#tool nuget:?package=FSharp.Interop.Dynamic&version=6.0.0
FSharp.Interop.Dynamic
Test and coverage badges are the last green CI run on master. CI fails the PR if any test is skipped, line coverage drops below 77%, or branch coverage drops below 100%.
F# operators for the Dynamic Language Runtime. target?Name, target?Name <- value, and !?target are the F# spelling of C# dynamic, with piping and 'T option lookups.
Docs: fsprojects.github.io/FSharp.Interop.Dynamic
This library sits on Dynamitey 3.0.3. It is the F# surface, not Dynamitey itself.
F# has no dynamic keyword. Use this when the member is not known at compile time: Expando/JSON bags, optional fields, method names from config, C# APIs that return dynamic, pythonnet, COM. Use ordinary F# when the type is in your project. Full argument: Why this library.
Version story
6.0.0 is the current package: netstandard2.0 + net10.0, Dyn.tryGet / Dyn.exists. That is a TFM break from 5.0.1.268 (net45 / netstandard1.6 / netstandard2.0). netstandard2.0 still covers current .NET Framework and .NET.
Install (6.0.0)
dotnet add package FSharp.Interop.Dynamic
open FSharp.Interop.Dynamic
open FSharp.Interop.Dynamic.Operators // optional: ?+?, ?=?, …
Quick start
open System.Dynamic
open FSharp.Interop.Dynamic
let o = ExpandoObject()
o?Name <- "Ada"
let name: string = o?Name
let hello: string = "HelloWorld"?Substring(0, 5)
Annotate the result type when F# cannot infer it. Void CLR methods need unit:
let items = ResizeArray<string>()
let _: unit = items?Add("x")
Check a member without throwing
let present: string option = o |> Dyn.tryGet "Name" // Some "Ada"
let missing: string option = o |> Dyn.tryGet "NoSuch" // None
o |> Dyn.exists "Name" // true
o |> Dyn.exists "NoSuch" // false
Lookup is Dynamitey InvokeGet. A present null is still present. A present value that cannot convert to 'T still throws — that is not a miss.
Pipe through Dyn
o |> Dyn.set "Name" "Ada"
let name: string = o |> Dyn.get "Name"
let hello: string = "HelloWorld" |> Dyn.invokeMember "Substring" (0, 5)
Target is last so piping works.
Binary operators
open FSharp.Interop.Dynamic.Operators
let n: int = 5 ?+? 4
let f: float = 5 ?+? 3.5
let s: string = "Hello" ?+? " World"
[1; 2; 3; 4] |> List.reduce (?+?)
Direct invoke
let add3: int -> int = !?(+) 3
add3 4 // 7
What ? does
| You write | DLR |
|---|---|
target?Name when 'T is not a function |
InvokeGet |
target?Name when 'T is a function, then apply |
InvokeMember |
target?Name <- value |
InvokeSet |
!?target |
Invoke on the target itself |
That is why target?Foo(1, 2) is a method call: application forces a function type.
Dynamitey
6.0.0 references Dynamitey 3.0.3. tryGet / exists do not wait on Dynamitey 4.0.0. The community continuation of Dynamitey is dynamitey-community/dynamitey; switching this package to it is #29.
You can still open Dynamitey for Build, Dynamic.Curry, DynamicObjects.Dictionary.
Caveats
- The DLR cannot see explicit interface members (same as C#
dynamic). - Not trim-safe or NativeAOT-safe.
- Do not build member names from untrusted input. SECURITY.md.
- Historical: .NET Core 2.0.0–2.0.2 broke
dynamicon nested types inside generics (#11). Current TFMs are fine.
Full list: Caveats.
Every F# snippet above is a test in Tests/ReadmeExamples.fs. pythonnet and SignalR sketches live on the why page and are not compiled here.
Build
Requires the .NET 10 SDK.
dotnet restore
dotnet build -c Release -warnaserror
dotnet test --project Tests/Tests.fsproj -c Release
Docs: dotnet tool install -g docfx --version 2.78.5, then dotnet build FSharp.Interop.Dynamic/FSharp.Interop.Dynamic.fsproj -c Release && docfx docfx/docfx.json.
Release: add the version's section to CHANGELOG.md, then tag v6.0.0 and push. Releasing.
Feedback and contributing
- Bugs and feature requests: open an issue. Include the F# and .NET versions and a minimal snippet.
- Security problems: do not open a public issue. Follow SECURITY.md.
- Code and docs: pull requests are welcome. CONTRIBUTING.md covers the process and what a PR needs before it merges.
Maintainers
fsprojects default: @fsprojectsgit.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Dynamitey (>= 3.0.3)
- FSharp.Core (>= 4.7.2)
- Microsoft.CSharp (>= 4.7.0)
-
net10.0
- Dynamitey (>= 3.0.3)
- FSharp.Core (>= 4.7.2)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on FSharp.Interop.Dynamic:
| Package | Downloads |
|---|---|
|
FCQRS
Package Description |
|
|
HOG.TezFs
Ultra high level F# Tezos library. |
|
|
Softellect.Sys
Softellect Sys Library provides primitive types and functionality needed by other Softellect packages. |
|
|
GMusicApi
Wrapper around https://github.com/simon-weber/gmusicapi |
|
|
FAkka.Server.Linux
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.