-
Notifications
You must be signed in to change notification settings - Fork 994
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
AssemblyLoadedContext for custom winforms designer serializer #12545
Comments
This should be a problem in the Winform Designer repo. When we package WinForms.Designer.SDK, the referenced package If WinForms.Designer.SDK removes the reference to the package System.CodeDom, then everything works fine here. At design time, @merriemcgaw @Tanya-Solyanik What do you think? |
@LeafShi1 - we need to know if System.CodeDOM.dll is included in PlatformManifest.txt for SDK for NET5, I don't know where this file is located in the GH, NET8 is here - https://github.com/dotnet/windowsdesktop/blob/release/8.0/src/windowsdesktop/src/sfx/PlatformManifest.txt before we remove it from the designer SDK package. And we need to confirm that all supported versions of .NET, starting with .NET5 work correctly with System.CodeDOM from the windowsdesktop SDK. |
NET5 is no longer supported since 2022, and the Release/5.0 branch has been deleted, so it is not certain whether System.CodeDOM.dll is included in the PlatformManifest.txt file of Net5 But from the created .Net5.0 project, it can be seen that System.CodeDOM.dll points to the correct version I verified with the customer's project CustomControl_Tab (2) 1.zip in diference .NET version, everything works fine (the package |
It can be found in Net6 and Net7: In NET6: https://github.com/dotnet/windowsdesktop/blob/7a6bfe6311159ed7f186dc670bb34dbb3d92a48f/pkg/windowsdesktop/sfx/PlatformManifest.txt#L31 |
This issue is tracked using issue #6200 in the WinForm Designer repo |
Thank you for checking. |
@merriemcgaw, @Tanya-Solyanik , Could you please comment when fix would be available for public? Do you have any release plan? |
We are still investigating in our internal repo. We do not have a solution just yet but will update once we do. |
@merriemcgaw , |
@svg2003 From the repro project, I found that the assembly containing the custom serializer was getting loaded in UserAssemblyLoadContext which generally loads the user code required at runtime. I am not sure if serializer is required at runtime. So I think, it will be better to use custom serializer using reflection by following syntax on the UserControl:
And include the custom serializer assembly as a server-side design time assembly as explained in scenario 2 in this document. The updated NuGet package structure will look like: This way, the serializer assembly will be loaded at design time only and the serializer will bind to the UserControl using reflection. |
@Shyam-Gupta , thank you for suggestion. Can you please elaborate, because right now it sounds a bit awkward and leads to errors. Correct me if I wrong, but seems instead of using strong types, you're suggesting to use hardcoded strings, to define link between 2 assemblies, which is for me looks very, very bad design and easy way to make a mistake. And I tried to change test project, to replace DesignerSerializer(typeof(MySerializer) with your suggested string, and found that inside Cache folder is copied only WinFormsCustomSerializer.dll, so custom serializer type just cannot be found. [19:01:10.389432] info: TypeResolution: type = System.Drawing.Design.UITypeEditor, TimeTaken = 0 ms. |
Strong type will require a project or assembly reference of From the error you are seeing, it appears that |
No, it is not the package. And I would prefer don't use packages, nor be enforced to select very bad design trade offs (strings instead of strong types; strange, hardcoded paths logic which seems is not documented and may be changed at any moment. packages, where there are non needed, etc, etc) . Let's start with very simple task - I have solution with 2 projects - custom control and custom serializer, which I somehow want to debug, i.e. want serializer logic is called, when I open custom control in the same solution. How solution structure should looks like at this case? |
I am sorry about this complexity. But it stems from the two-process architecture which we have to create in order to support .NET designer and it required a nearly complete rewrite of the designer logic. I would encourage you to refer to this document in which @KlausLoeffelmann has explained this complexity nicely. He has also documented the recommended project structure. The NuGet package path logic has been documented here and it cannot be changed easily. @KlausLoeffelmann Please let us know if there is any better way to support the scenario mentioned in the repro steps of this issue. |
Seems Server is using DesignDependecies element from DesignToolsServerManifest.json. "DesignDependencies": [ |
Environment
MSVS 17.11.6
.NET version
net8
Did this work in a previous version of Visual Studio and/or previous .NET release?
no
Issue description
I'm trying to port netframework's custom designer serializer into net8.
I've created separate project, using Microsoft.WinForms.Designer.SDK, and put serializer there, so it's instantiated by WinFormsDesigner code, but assembly is loaded into UserAssemblyLoadContext, whereas types, returned by IDesignerSerializerManager - are from Default context.
As the result, it's impossible to mix them together, due to even type cast would give an exception:
[18:10:21.375488] fail: [WinFormsCustomSerializer]: Ex: System.InvalidCastException: [A]System.CodeDom.CodeStatementCollection cannot be cast to [B]System.CodeDom.CodeStatementCollection. Type A originates from 'System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context 'Default' at location 'C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.11\System.CodeDom.dll'. Type B originates from 'System.CodeDom, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context '"UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0' at location 'c:\views!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll'.
winforms-designerServerContext.zip
Steps to reproduce
1. Create separate project for custom serializer, using Microsoft.WinForms.Designer.SDK:
2. Add some dummy serializer there:
3. Create winforms project and add some user control there, with customer serializer:
4. Use that control on winforms:
5. Try to change control (say, size), and save it.
It will give an exception in log (due to mismatched types)
Here is how serializer is created (by WinFormsServer):
[18:10:21.363486] fail: [WinFormsCustomSerializer]: Creating from at System.Environment.get_StackTrace()
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at MyDesignServer.MySerializer..ctor()
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.DesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.DesignerSerializationManager.System.ComponentModel.Design.Serialization.IDesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.ComponentListCodeDomSerializer.Serialize(IDesignerSerializationManager manager, IDictionary objectData, IDictionary objectState, IList shimObjectNames)
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.Close()
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent.Serialize(UndoEngine engine, Object component, MemberDescriptor member)
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent..ctor(UndoEngine engine, ComponentChangingEventArgs e, Boolean serializeBeforeState)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ComponentChanging(ComponentChangingEventArgs e)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.OnComponentChanging(Object sender, ComponentChangingEventArgs e)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Host.RemoteDesignerHost.System.ComponentModel.Design.IComponentChangeService.OnComponentChanging(Object component, MemberDescriptor member)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.ResizeBehavior.OnMouseMove(Glyph glyph, MouseButtons button, Point adornerCoordinates)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.BehaviorService.OnMouseMove(InputDispatchEventArgs e)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.BehaviorService.Dispatcher.OnMouseMove(InputDispatchEventArgs e)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.Input.InputMessageHandler.HandleRequest(InputMessageRequest request)
[18:10:21.369486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestHandler
2.Microsoft.DotNet.DesignTools.Protocol.Endpoints.IRequestHandler.HandleRequest(Request request) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestManager.HandleRequestAsync(String name, Request request) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1.AsyncStateMachineBox1.ExecutionContextCallback(Object s) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1.AsyncStateMachineBox1.MoveNext(Thread threadPoolThread) [18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1.AsyncStateMachineBox`1.MoveNext()[18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
[18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.WndProc(Message& m)
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Server.Window.ServerWindow.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at Windows.Win32.PInvoke.DispatchMessage(MSG* lpMsg)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ComponentManager.Microsoft.Office.IMsoComponentManager.FPushMessageLoop(UIntPtr dwComponentID, msoloop uReason, Void* pvLoopData)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(msoloop reason, ApplicationContext context)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(msoloop reason, ApplicationContext context)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Server.DesignToolsServer.<>c__DisplayClass55_0.b__1()
[18:10:21.374487] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[18:10:21.374487] fail: [WinFormsCustomSerializer]: Serializer constructor: c:\views!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll.
[18:10:21.374487] fail: [WinFormsCustomSerializer]: Context: "UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0
Diagnostics
The text was updated successfully, but these errors were encountered: