Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC: explaining EmbeddedResource parameter would be super helpful #1315

Open
daz10000 opened this issue May 28, 2020 · 4 comments
Open

DOC: explaining EmbeddedResource parameter would be super helpful #1315

daz10000 opened this issue May 28, 2020 · 4 comments

Comments

@daz10000
Copy link

daz10000 commented May 28, 2020

I lost a few hours of my life to syntax for the embedded resource parameter, and thought it might be helpful to document what was missing. I worked out some of it from bug reports and random experimentation and finally peeking into a DLL, but some docs would have saved an enormous amount of time

explain

  • Embedded resource parameter is absolutely required when a DLL depends on another DLL using a path to a data example (e.g json provider, csv provide)
  • an example of how to embed the resource
  • The syntax for the embedded resource parameter, e.g. the likely substitution of any slashes for dots on the path, and the need to refer to both the dependent DLL, path to the resource (that was my final hurdle) e.g MyDll, MyDll.path.to.resource.xml

it's probably also worth explaining what happens if you don't do this (you get a really cryptic problem from the type provider using the path as an example of the CSV file and it's really evil because it works in the first DLL but the dependent DLL just gets a single CSV column with the path as its name.

Right now the only resources you have are bug reports where the mechanism wasn't working temporarily, and partial examples. One simple end to end example, and possibly references to tools like ildasm or other things for interest affecting the embedded resource name mangling would be helpful.

Overall code works wonderfully, but this is a pretty nasty pit to fall into which could be avoided with a paragraph of documentation.

@dsyme
Copy link
Contributor

dsyme commented Jun 1, 2020

@daz10000 Could you write out a step by step to recreate the cryptic problems mentioned?

Thanks

@daz10000
Copy link
Author

daz10000 commented Jun 2, 2020

fair call! That's a pretty cryptic complaint.I would be happy to send a pull request for some better documentation but wasn't quite sure where to put this. I think the issue is applicable to each of the type providers, but I encountered it with the CSV provider.

To reproduce

  • make two projects ProjA (e.g. a console app) and ProjB (a library)
  • add the FSharp.Data package to the second project ProjB
  • create a type provider that references an example document with a path relative to ProjB eg example/MyCSV.csv e.g.
Country,Capital
Australia,Canberra
UK,London
Germany,Berlin
  • Finish up code for ProjB - all works, nicely referencing the example csv file
namespace ProjB

type CapitalCSV = FSharp.Data.CsvProvider<"example/MyCSV.csv",HasHeaders=true>

module Say =
    let rows = CapitalCSV.Load("myfile.csv").Rows
    for row in rows do
        printfn "Capital=%s" row.Capital
  • Now have ProjA refer to ProjB as a dependency and use the type provider
    dotnet add reference ../ProjB/ProjB.fsproj
  • Add some code in ProjA that uses the type provider in ProjB e.g.
[<EntryPoint>]
let main argv =
    let rows = ProjB.CapitalCSV.Load("mycsvfilewithcountries.csv").Rows
    for row in rows do
        printfn "Country=%s Capital=%s" row.Country row.Capital

    0 // return an integer exit code
  • This will fail because the second project ProjA re-interprets the path to the example CSV file The CSV provider takes the path 'example/MyCSV.csv` and takes it as a literal CSV file since it can't find it., so you get a tooltip like this

image

  • Have no fear though, Embedded resources to the rescue, we can just slightly alter the project B fsproj to make the example file an embedded resource (the docs hint at this but don't explain how)
    <Compile Include="Library.fs" />
    <EmbeddedResource Include="example/MyCSV.csv"/>
  </ItemGroup>
  • So far so good, but what to put in the argument for the EmbeddedResource argument to the type provider? One might naiively try
    • "example/MyCSV.csv" or "MyCSV.csv" or
    • "ProjB/example,MyCSV.csv"
  • but the magic incantation in projB to get it to work is
    type CapitalCSV = FSharp.Data.CsvProvider<"example/MyCSV.csv",HasHeaders=true,EmbeddedResource="ProjB, ProjB.example.MyCSV.csv">
  • Basically EmbeddedResource="AssemblyName, path.with.no.slashes.to.file.csv

Maybe this could be converted into a short example and put somewhere central - it's applicable to all the providers. Maybe this is common knowledge but I had to work out the syntax for the embedded resource experimentally peeking inside the dll itself and looking at hints from other bug reports.

Also attaching full working example which might be handy. It's pinned to netcore3.1 in global.json just because I have netcore 5 preview floating around and it's breaking a few things but should be fine without the global.json files in practice.

TPPathDemo.zip

@nhirschey
Copy link
Contributor

@daz10000, see here (#1334) for some new documentation of this on the JsonProvider. That’s at least 3 of us hitting this cryptic info in the past 12 months.

Maybe you can do a pull request adding similar info to the CsvProvider docs. Or, a new short EmbeddedResource.fsx document using FSharp.Formatting explaining your response to Don above for JsonProvider and CsvProvider? Your explanation of the paths/Library naming issue is more complete than the new JsonProvider doc text. And it makes more sense to have one full explanation as you mention covering all the providers and then link to it from the other provider docs.

@nhirschey
Copy link
Contributor

@daz10000, another related issue #1191

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants