runtime: IComponent is missing designer attributes
In particular, IComponent
is missing the following two attributes, which were defined on .NET Framework:
[Designer("System.ComponentModel.Design.ComponentDesigner, " + AssemblyRef.SystemDesign, typeof(IDesigner))]
[Designer("System.Windows.Forms.Design.ComponentDocumentDesigner, " + AssemblyRef.SystemDesign, typeof(IRootDesigner))]
This affects both designer and runtime IDesignerHost
scenarios. cc @ericstj.
While we’ve worked around this in our designer by hard-coding knowledge of IComponent
’s missing attributes in our own IDesignerHost
implementation, third-parties would be hard-pressed to do the same for runtime scenarios where the designer is hosted in an application at runtime. An example of such a scenario is DevExpress’s Reporting library where they allow a report designer based on CodeDom serialization to embedded directly into an end user application. This is a very meaningful for certain line-of-business apps.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 20 (20 by maintainers)
The repro would be to create an
IComponent
instance and callTypeDescriptor.CreateDesigner(...)
with the base type astypeof(IDesigner)
and then again withtypeof(IRootDesigner)
. Today, both calls will returnComponentDesigner
, but the second should returnComponentDocumentDesigner
.This blocks designer scenarios where the user opens a component or control as a root designer. When the user drops some component on a form designer, the designer host will already had a root component. So, it’ll ask to create a designer with a base type of
IDesigner
. However, if the user double-clicks a component or control in the Solution Explorer, it’ll be opened as the root component. So, the designer host will ask to create a designer with a base type ofIRootDesigner
. Without this change, the latter case is broken. I can work around it in the new designer, but’ll still be broken from runtime designer hosting scenarios.https://github.com/dotnet/winforms/blob/6a4da4de1c03d3778c63b2b0195045d00c490fd5/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignSurface.cs#L283-L305
Everything is done via reflection using
TypeDescriptor
andPropertyDescriptor
, typically on runtime objects and types. In the classic designer, there was a filtering done to hide runtime properties that didn’t appear on reference assemblies. This was necessary to hide properties that were available on runtime objects that didn’t appear in the TFM that the project was referencing, since VS typically ran on a different TFM. However, the designer has always worked on runtime types and object instances.In the .NET Core designer, we construct a server process (much like WPF does) using a runtimeconfig.json and deps.json that matches up with the user’s project. That way, the process runs using the runtime, NuGet references, etc. that the user’s app targets. So, the designer will be running on the same RID that the user is targeting. So, the runtime assemblies that it needs are in the default
AssemblyLoadContext
.You’re right… somehow I can’t read anymore and read
IRootDesigner
😆So the following attributes need to be applied to all the types that had them in desktop:
These types should be pushed down as low as necessary to apply them in all cases.
In places where these attributes depend on other types, like here https://github.com/dotnet/runtime/blob/0e23ef47ff8a2de6a5b5898a849ba00303aba8df/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DesignerAttribute.cs#L23
We should avoid that dependency by using type name, as is done here: https://github.com/dotnet/runtime/blob/0e23ef47ff8a2de6a5b5898a849ba00303aba8df/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ToolboxItemAttribute.cs#L40
cc @Anipik since this is related to work he’s doing WRT attributes in references.