Code Monkey home page Code Monkey logo

fsharp.typeproviders.sdk's Introduction

Issue Stats Issue Stats

The F# Type Provider SDK

The F# Type Provider SDK is two things:

  1. The ProvidedTypes.fs API files you need to author type providers

  2. Documentation and samples on type provider creation

This package is actively seeking contributions.

Build status

Build status (Windows) Build Status (MacOS, mono)

The ProvidedTypes API - Adding the Files

Building a type provider nearly always starts with adding these files to your project:

  • ProvidedTypes.fsi
  • ProvidedTypes.fs

If using Paket, you can add code files by direct GitHub references like this and reference the files in a project file like this.

Type providers may be used in projects that generate .NET Standard code or target other .NET Frameworks than that being used to execute the F# compiler.

The ProvidedTypes API - A Basic Type Provider

Here is a basic erasing type provider using the Provided Types API:

open ProviderImplementation
open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
open System.Reflection

[<TypeProvider>]
type BasicProvider (config : TypeProviderConfig) as this =
    inherit TypeProviderForNamespaces (config)

    let ns = "StaticProperty.Provided"
    let asm = Assembly.GetExecutingAssembly()

    let createTypes () =
        let myType = ProvidedTypeDefinition(asm, ns, "MyType", Some typeof<obj>)
        let myProp = ProvidedProperty("MyProperty", typeof<string>, isStatic = true, getterCode = (fun args -> <@@ "Hello world" @@>))
        myType.AddMember(myProp)
        [myType]

    do
        this.AddNamespace(ns, createTypes())

[<assembly:TypeProviderAssembly>]
do ()

Some unit testing helpers

The SDK includes a file

  • ProvidedTypesTesting.fs

which is sometimes incorporated into a type provider to help enable unit testing. For examples of how this is used, see uses of the helpers in the FSharp.Data library such as

Sometimes unit test DLLs incorporate the entire type provider implementation, and sometimes they use InternalsVisibleTo.

The unit testing helpers aren't really an official, documented part of the DK - caveat emptor.

Technical Notes

Using Type Providers with .NET SDK 2.0 Projects and dotnet build

See How to enable type providers with new-style .NET SDK project files, dotnet build, .NET Standard and .NET Core programming

Some Type Provider terminology

  • TPRTC - Type Provider Referenced Component, e.g. FSharp.Data.dll.

    • This is the component referenced by #r or -r: on the command line or other confugration of a host tool

    • May be the same physical file as the TPDTC.

    • Contains either a TypeProviderAssembly() attribute indicating that this component is also a TPDTC, or TypeProviderAssembly("MyDesignTime.dll") attribute indicating that the name of the design time component.

    • A type provider package may have multiple such DLLs for different target platforms, e.g.

      lib\net45\FSharp.Data.dll
      lib\netstandard2.0\FSharp.Data.dll
      
    • TPRTCs are normally .NET Framework 4.x, .NET Standard 2.0 or some portable profile component.

  • TPDTC - Type Provider Design Time Component, e.g. FSharp.Data.DesignTime.dll.

    • The DLL that gets loaded into host tools.

    • May be the same physical file as the TPRTC.

    • This component includes the ProvidedTypes.fs/fsi files from the type provider SDK.

    • TPDTCs are currently .NET Framework 4.x. They can also be .NET Standard 2.0 components, see below

  • Host tool - Either fsc.exe, fsi.exe or some tool hosting FSharp.Compiler.Service.dll such as devenv.exe or FsAutoComplete.exe

How the TPDTC is found and loaded

Currently, host tools look for TPDTC DLLs alongside the TPRTC DLL. For simple type providers, these DLLs are the same. When executing using .NET Framework, the host tool uses Assembly.LoadFrom to load this component.

See Type provider design-time DLLs should be chosen more appropriately for a proposal to change the rules to allow TPDTC components to be found more usefully, and in particular for different TPDTC components to be loaded depending on the execution environment of the host tooling.

Making a .NET Standard 2.0 TPDTC

It will be increasingly common to make type providers where the TPDTC is a .NET Standard 2.0 component. In the very simplest case, there will just be one happy .NET Standard 2.0 component MyTypeProvider.dll acting as both the TPDTC and TPRTC. Such a type provider will eventually be loadable into all F# tooling.

However, today, for a TPDTC to be .NET Standard 2.0, it must be loadable into host tools using .NET Framework 4.6.1 or Mono 5.x, the most common platforms for execution of F# tooling. Because .NET Framework 4.6.1 doesn't fully support .NET Standard 2.0, this can only be done if the TPDTC ships alongside some facade DLLs. Currently the following facade DLLs are needed alongside the TPDTC:

    <!-- These files are the facades necessary to run .NET Standard 2.0 components on .NET Framweork 4.6.1 (.NET Framework 4.7 will -->
    <!-- come with these facades included). Because the type provider is a .NET Standard 2.0 component, the deployment of the type -->
    <!--  provider must include these facade DLLs if it is to run hosted inside an F# compiler executing using  .NET Framework 4.6.1 or Mono 5.0. -->
    <!-- -->
    <!-- We are not yet sure if the presence of these files will prevent an otherwise .NET Standard 2.0 type provider running inside a -->
    <!-- F# compiler executing using .NET CoreApp 2.0, as until recently F# compilers running using .NET CoreApp 2.0 do not load type providers correctly. -->
    <None Include="..\..\packages\NETStandard.Library.NETFramework\build\net461\lib\netstandard.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Include="..\..\packages\NETStandard.Library.NETFramework\build\net461\lib\System.Reflection.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Include="..\..\packages\NETStandard.Library.NETFramework\build\net461\lib\System.Runtime.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>

Packaging your Type Provider

It is important that the design-time assemblies you use (if any) are not loaded at runtime. To ensure this does not happen, when you distribute a Nuget package for your Type Provider you must provide an explicit list of project references for consumers to include. If you do not, every assembly you publish in the package will be included, which can lead to design-type only references being loaded at runtime. To reference only a subset of assemblies, see the Nuget documetation or the Paket documentation.

Explicit construction of code: MakeGenericType, MakeGenericMethod and UncheckedQuotations

Some type providers need to build code via explicit calls to FSharp.Quotations.Expr.* rather than via quotation literals. Frequently, this is needed when code must instantiate generic methods or types. However, in some cases limitations of the F# quotations API are reached.

In these cases, follow these rules

  1. Always use ProvidedTypeBuilder.MakeGenericType(type, typeArguments) rather than type.MakeGenericType(typeArguments)
  2. Always use ProvidedTypeBuilder.MakeGenericMethod(methInfo, methTypeArguments) rather than methInfo.MakeGenericType(methTypeArguments)
  3. Where necessary open open ProviderImplementation.ProvidedTypes.UncheckedQuotations and make quotation nodes representing calls and other operations using Expr.CallUnchecked.

If you don't do this you may get errors like

The type provider 'FSharp.Configuration.ConfigTypeProvider+FSharpConfigurationProvider' reported an error: Type mismatch when building 'args': invalid parameter for a method or indexer property. Expected 'System.Collections.Generic.IEnumerable`1[System.String]', but received type 'System.Collections.Generic.IEnumerable`1[System.String]'.�Parameter name: receivedType

or

System.InvalidOperationException: the operation is not valid due to the current state of the object. at System.Reflection.MemberInfo.get_MetadataToken() in f:\dd\ndp\clr\src\BCL\system\reflection\memberinfo.cs:line 65

Resources

For advice on how to get started building a type provider, check out:

Support and community

Building

Use

build.sh RunTests

or

build.cmd RunTests

Library license

The library is available under the MIT License. For more information see the License file in the GitHub repository.

Maintainer(s)

The default maintainer account for projects under "fsprojects" is @fsprojectsgit - F# Community Project Incubation Space (repo management)

fsharp.typeproviders.sdk's People

Contributors

7sharp9 avatar alfonsogarciacaro avatar baronfel avatar dedale avatar dsyme avatar forki avatar fsgit avatar fsprojectsgit avatar haraldsteinlechner avatar jand42 avatar kbattocchi avatar matiasdd avatar matthid avatar mavnn avatar ptrelford avatar reedcopsey avatar sergey-tihon avatar skovlund avatar smoothdeveloper avatar takemyoxygen avatar tarmil avatar thorium avatar tihan avatar tpetricek avatar vilinski avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.