(The changes described applies to VS2022 also as of builds in 2026 and onwards, no new VSIX download, can run side by side VS2022, VS2026)
How the GAC masked the real problems, how NuGet exposed them, and how we finally fixed the root cause
Over the last development cycle, weâve finally untangled one of the most persistent and subtle problems in the Visual Studio integration story for MDriven: loadâcontext conflicts. These issues have existed for years, but they were largely invisible until we moved away from the Global Assembly Cache (GAC) and fully embraced NuGet distribution.
VS2026 gave us the opportunityâand the pressureâto understand the problem completely and fix it at the foundation.
đ§Š The Hidden Simplicity of the GAC Era
Before NuGet became the standard way to deliver MDriven updates, Visual Studio relied heavily on the GAC. That meant:
- There was exactly one version of each MDriven assembly on the machine
- Visual Studio always loaded that version
- The project also loaded that version
- All types came from the same physical file
- Loadâcontext issues simply could not occur
This uniformity made many complexities disappear. But it came at a huge cost:
- You couldnât easily ship new versions
- You couldnât have perâproject versioning
- You couldnât reliably test different versions sideâbyâside
- You couldnât use NuGet the way modern .NET development expects
The GAC made things look stable, but it also froze the ecosystem.
đ§ The Moment Everything Broke: Leaving the GAC
When we removed the GAC dependency and fully supported NuGet, Visual Studio suddenly had two independent sources for MDriven assemblies:
- The userâs project (NuGet)
- The VSIX plugin folder
And because they had the same name and the same public key, Visual Studio happily loaded:
MDriven.Handlesfrom the projectMDriven.Handlesfrom the VSIX
âŚinto two different load contexts.
From Visual Studioâs perspective:
TypeAfrom the project âTypeAfrom the VSIX- Even if the bytes were identical
- Even if the versions matched
- Even if everything âshouldâ work
This was the silent root cause behind:
- Reflection failures
- Designer crashes
- Codeâgen errors like â
.AddRangedoes not existâ - Random behavior depending on load order
- Years of unpredictable designer instability
The GAC had masked the problem. NuGet exposed it brutally.
đ The Breakthrough: Give the VSIX Its Own Assembly Identity
The real fix was to ensure that Visual Studio could never confuse the two worlds again.
We changed the signing key for all designâtime assemblies in the VSIX:
- Runtime/NuGet assemblies:
PublicKeyToken=46a833be9e90de8c - Designâtime/VSIX assemblies:
PublicKeyToken=8284d47cc38744ec
This guarantees:
- The VSIX loads its own assemblies
- The project loads its own assemblies
- Visual Studio never merges or crossâbinds them
- Loadâcontext conflicts disappear entirely
If developers encounter assemblies signed with the designâtime key: They are intentional, safe, and required for Visual Studio stability.
đ The Second Breakthrough: Only Transport Simple Data Across the Boundary
Once the loadâcontext separation was in place, the next insight became obvious:
Never pass projectâloaded objects directly into the VSIX designers.
Instead:
- Extract simple DTOs from the project
- Send those DTOs into the designer
- Let the designer operate in its own isolated world
- Send DTOs back after design
- Rehydrate them into real project objects
This eliminates all crossâcontext type confusion.
đ§ We Actually Learned This EarlierâBut Only Partially
Back in VS2022, when .NET 6 WinForms designers moved outâofâprocess, we were forced to adopt a DTO strategy for that designer. It worked beautifully.
But the rest of the designersâespecially .NET Framework 4.8âwere still inâprocess, so the old patterns persisted.
With VS2026, we finally unified the approach:
All designers now use the DTO strategy.
Even .NET 4.8 designers. Even legacy designers. Everything.
And suddenly:
- The longâstanding codeâgen issues disappeared
- Designer reliability improved dramatically
- The extension became predictable instead of mystical
đ The Light at the End of the VSIX Tunnel
This has been a long journeyâyears of odd behavior, reflection quirks, and designer inconsistencies. But with:
- Unique designâtime assemblies
- A strict DTO boundary
- Unified handling across all designers
- A clean separation between runtime and designâtime worlds
- A modern NuGetâfriendly architecture
âŚwe finally have a stable foundation for the future.
The VS2026 VSIX is the most robust, predictable, and maintainable version weâve ever shipped.
And for the first time in a long time, we can say with confidence:
We finally see the light in the long VSIX tunnel.
đ§ A Cleaner Path for the OCL Editor: Direct TypeSystem From the ModlrâModel
Historically, the OCL editor inside EcoHandles (WinForms) obtained its model information by reflecting the generated code and extracting the IEcoTypeSystem from the compiled EcoSpace. That approach worked, but it had two major drawbacks:
- It crossed the Project â VSIX boundary using real types, which we now avoid completely.
- It forced a full codegen + compile cycle before the OCL editor could see any model changes.
With the new architecture, that approach no longer fits. Since we now enforce a strict DTO boundary between the project world and the VSIX world, we needed a cleaner, safer, and more predictable way to supply the OCL editor with model metadata.
The new approach is much simpler:
We now take the IEcoTypeSystem directly from your ModlrâModel.
This gives you a dramatically better experience:
- You can edit your model
- Save it
- And instantly see the updated types in the OCL editor
- No codegen, no compile, no waiting
The only requirement is that your ModlrâModel is open while you work in the OCL editor. Given the speed and clarity this provides, itâs a very small price to pay.
â ď¸ A Small but Important GOTCHA: Packages
The ModlrâModelâs type system always includes all packages defined in the model. However, your runtime EcoSpace can be configured to use only a subset of those packages.
This feature was originally intended to reduce the size of the runtime type system, but in practice:
- It adds complexity
- It creates mismatches between designâtime and runtime
- It causes confusing runtime errors when parts of the model âdisappearâ
- And it provides very little real benefit
Our recommendation is simple:
Always include all packages in your EcoSpace.
This ensures:
- The OCL editor sees the same model as your runtime
- No missing classes or associations
- No âwhy does this work in the designer but not at runtimeâ mysteries
- A consistent, predictable modeling experience
