diff --git a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs index 0bb778c95..d69484bac 100644 --- a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs +++ b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs @@ -725,34 +725,58 @@ module internal ProviderHelpers = yield m :> _ - | Schema _ -> - let getSchemaCode _ = - if parseResult.IsUri then - <@ - Async.RunSynchronously( - asyncReadTextAtRuntimeWithDesignTimeRules - defaultResolutionFolder - resolutionFolder - formatName - encodingStr - valueToBeParsedOrItsUri - ) - @> - else - <@ new StringReader(valueToBeParsedOrItsUri) :> TextReader @> + | Schema _ -> () // GetSchema is generated below, outside this block + + + // GetSchema is generated for Schema sources regardless of EmbeddedResource, + // so that deployed assemblies can validate XML against the schema at runtime. + match source with + | Schema _ -> + let getSchemaCode _ = + if parseResult.IsResource then + // EmbeddedResource was specified and the resource was found at design time. + // At runtime, read the schema from the embedded resource in the user's assembly. + let parts = resource.Split(',') + let asmName = parts.[0].Trim() + let resName = parts.[1].Trim() + + <@ + // Assembly.Load handles assemblies not yet in AppDomain + let loadedAsm = System.Reflection.Assembly.Load(asmName) + + // Do not use 'use' here — the reader lifetime is managed by + // parseSchemaFromTextReader (XmlReader with CloseInput=true) + let stream = loadedAsm.GetManifestResourceStream(resName) + new System.IO.StreamReader(stream) :> TextReader + @> + |> spec.CreateFromTextReaderForSampleList // hack: this will actually parse the schema + elif parseResult.IsUri then + <@ + Async.RunSynchronously( + asyncReadTextAtRuntimeWithDesignTimeRules + defaultResolutionFolder + resolutionFolder + formatName + encodingStr + valueToBeParsedOrItsUri + ) + @> + |> spec.CreateFromTextReaderForSampleList // hack: this will actually parse the schema + else + <@ new StringReader(valueToBeParsedOrItsUri) :> TextReader @> |> spec.CreateFromTextReaderForSampleList // hack: this will actually parse the schema - // Generate static GetSchema method - yield - ProvidedMethod( - "GetSchema", - [], - typeof, - isStatic = true, - invokeCode = getSchemaCode - ) - :> _ - + // Generate static GetSchema method + yield + ProvidedMethod( + "GetSchema", + [], + typeof, + isStatic = true, + invokeCode = getSchemaCode + ) + :> _ + | _ -> () ] |> spec.GeneratedType.AddMembers diff --git a/tests/FSharp.Data.Reference.Tests/FSharp.Data.Reference.Tests.fsproj b/tests/FSharp.Data.Reference.Tests/FSharp.Data.Reference.Tests.fsproj index 8c9ae799c..464880064 100644 --- a/tests/FSharp.Data.Reference.Tests/FSharp.Data.Reference.Tests.fsproj +++ b/tests/FSharp.Data.Reference.Tests/FSharp.Data.Reference.Tests.fsproj @@ -11,6 +11,7 @@ + diff --git a/tests/FSharp.Data.Reference.Tests/XmlProvider.fs b/tests/FSharp.Data.Reference.Tests/XmlProvider.fs new file mode 100644 index 000000000..7f26c8033 --- /dev/null +++ b/tests/FSharp.Data.Reference.Tests/XmlProvider.fs @@ -0,0 +1,9 @@ +module FSharp.Data.Reference.Tests.XmlProvider + +open NUnit.Framework +open FsUnit + +[] +let ``GetSchema works for XmlProvider with Schema and EmbeddedResource`` () = + let schema = FSharp.Data.Tests.XmlProvider.XmlSchemaWithEmbeddedResource.GetSchema() + schema.Count |> should equal 1 diff --git a/tests/FSharp.Data.Tests/XmlProvider.fs b/tests/FSharp.Data.Tests/XmlProvider.fs index e4f538d9d..6d355070e 100644 --- a/tests/FSharp.Data.Tests/XmlProvider.fs +++ b/tests/FSharp.Data.Tests/XmlProvider.fs @@ -1320,3 +1320,7 @@ let ``Inline schemas as overrides replace value-based inference when present`` ( sample[1].Value.GetType() |> should equal (typeof) // (Note the types in the inline schemas are automatically transformed to options as needed // when another node does not define any value for the given property) + +// Used by FSharp.Data.Reference.Tests to verify that GetSchema works with EmbeddedResource +type XmlSchemaWithEmbeddedResource = + XmlProvider