From 239d952e05d6045d625e4e863f1bcb1c9af66897 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 18:48:19 +0000 Subject: [PATCH 1/4] Fix #1310: GetSchema now works with EmbeddedResource for XSD schemas When XmlProvider is used with Schema and EmbeddedResource, the EmbeddedResource parameter was previously ignored at runtime because GetSchema was inside the 'if not parseResult.IsResource then' guard that suppressed it when a resource was found at design time. This fix moves GetSchema generation outside that guard and adds an IsResource branch that reads the XSD from the embedded resource at runtime using AppDomain.CurrentDomain.GetAssemblies(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../CommonProviderImplementation/Helpers.fs | 77 ++++++++++++------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs index 0bb778c95..23f5f711b 100644 --- a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs +++ b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs @@ -725,34 +725,59 @@ 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() + + <@ + let loadedAsm = + System.AppDomain.CurrentDomain.GetAssemblies() + |> Array.find (fun a -> a.GetName().Name = 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 From 644162c10a3b75d33af7e1de46afd8be9a837de2 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 19:33:37 +0000 Subject: [PATCH 2/4] Add test case for GetSchema with EmbeddedResource in XSD schemas (#1620) * Initial plan * Add test case for GetSchema with EmbeddedResource in XSD schemas Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com> --- .../FSharp.Data.Reference.Tests.fsproj | 1 + tests/FSharp.Data.Reference.Tests/XmlProvider.fs | 9 +++++++++ tests/FSharp.Data.Tests/XmlProvider.fs | 4 ++++ 3 files changed, 14 insertions(+) create mode 100644 tests/FSharp.Data.Reference.Tests/XmlProvider.fs 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 7e34da43a..f0d6baf44 100644 --- a/tests/FSharp.Data.Tests/XmlProvider.fs +++ b/tests/FSharp.Data.Tests/XmlProvider.fs @@ -1312,3 +1312,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 From f9687ff89934a41b96e5b81c475543a8c3675c85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Feb 2026 19:47:41 +0000 Subject: [PATCH 3/4] Fix GetSchema EmbeddedResource: use Assembly.Load instead of AppDomain search Replace AppDomain.CurrentDomain.GetAssemblies() |> Array.find with System.Reflection.Assembly.Load(asmName), which handles assemblies not yet loaded into the AppDomain (e.g. when called from a test project). Suggested in Copilot SWE PR #1623. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../CommonProviderImplementation/Helpers.fs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs index 23f5f711b..d69484bac 100644 --- a/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs +++ b/src/FSharp.Data.DesignTime/CommonProviderImplementation/Helpers.fs @@ -741,9 +741,8 @@ module internal ProviderHelpers = let resName = parts.[1].Trim() <@ - let loadedAsm = - System.AppDomain.CurrentDomain.GetAssemblies() - |> Array.find (fun a -> a.GetName().Name = asmName) + // 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) From 775fd1ac18dfa4df3aa4b9e01de84862da3e15b1 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 22:06:25 +0000 Subject: [PATCH 4/4] Fix GetSchema EmbeddedResource: use Assembly.Load instead of AppDomain search (#1623) * Initial plan * Fix CI: Use Assembly.Load instead of AppDomain.GetAssemblies for EmbeddedResource schema Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com> Co-authored-by: Don Syme