Skip to content
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

IComponent is missing designer attributes #31428

Closed
DustinCampbell opened this issue Nov 7, 2019 · 20 comments · Fixed by #41145 or #44774
Closed

IComponent is missing designer attributes #31428

DustinCampbell opened this issue Nov 7, 2019 · 20 comments · Fixed by #41145 or #44774

Comments

@DustinCampbell
Copy link
Member

DustinCampbell commented Nov 7, 2019

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.

@ericstj
Copy link
Member

ericstj commented Nov 7, 2019

We would have to push DesignerAttribute down from System.ComponentModel.TypeConverter into System.ComponentModel.Primitives (or lower, like System.ObjectModel) in order to do this. We don't normally make such changes in servicing. How critical is this? Should we be rushing to get this in 3.1 (it's effectively done) or do you have a workaround / not need this for 3.x?

@ericstj ericstj self-assigned this Nov 7, 2019
@DustinCampbell
Copy link
Member Author

I'm working around it in the WinForms designer, so we don't need it for 3.1. We'll need it eventually as runtime IDesignerHost scenarios start shaping up (.NET 5?). Otherwise, third-party scenarios won't work properly unless they add similar hacks.

@ericstj
Copy link
Member

ericstj commented Nov 7, 2019

Got it, we can fix in 5.0. We should also push the EditorAttribute down (and potentially any other related attributes) so that we can address these and related issues.

@DustinCampbell
Copy link
Member Author

I'm betting there's other DesignerAttributes missing too (e.g. Process?), but I only found this one as we've started working on the component tray.

@ericstj
Copy link
Member

ericstj commented Nov 7, 2019

@Tanya-Solyanik
Copy link
Member

Serializers, Editor, and typeDescriptionProvider are definitely important if any runtime scenario is using property grid or design time serialization. For the toolbox we are using a different approach than what was used in the .NET designer, and I don't know about the runtime uses for it. Maybe devexpress reports use it.

@DustinCampbell
Copy link
Member Author

DesignerSerializerAttribute is important, since it allows a component/control to provide custom CodeDom serialization. For example, Control provides ControlCodeDomSerializer to generate SuspendLayout()/ResumeLayout() calls in InitializeComponent().

I'm pretty sure that RootDesignerSerializerAttribute has been deprecated since .NET 2.0, so I can't see any reason to bother with it.

@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 5.0 milestone Feb 1, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@ericstj
Copy link
Member

ericstj commented Jul 9, 2020

@DustinCampbell is this still important or are you OK with your workarounds? Fixing this requires moving types around which is not something we like to do unless there is a very strong need.

@ericstj ericstj removed the untriaged New issue has not been triaged by the area owner label Jul 9, 2020
@ericstj ericstj assigned DustinCampbell and unassigned ericstj Jul 9, 2020
@ericstj
Copy link
Member

ericstj commented Jul 20, 2020

So the following attributes need to be applied to all the types that had them in desktop:

T:System.ComponentModel.DesignerAttribute
T:System.ComponentModel.Design.Serialization.DesignerSerializerAttribute
T:System.ComponentModel.EditorAttribute
T:System.ComponentModel.ToolboxItemAttribute
T:System.ComponentModel.TypeDescriptionProviderAttribute

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

We should avoid that dependency by using type name, as is done here:

_toolboxItemTypeName = "System.Drawing.Design.ToolboxItem, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";

cc @Anipik since this is related to work he's doing WRT attributes in references.

@DustinCampbell
Copy link
Member Author

@safern, @ericstj: It looks like one of the [Designer] attributes was added incorrectly to IComponent. The attribute for ComponentDocumentDesigner should specify a second argument of type IRootDesigner to distinguish the two designers. Can we reopen and address this?

@safern
Copy link
Member

safern commented Oct 28, 2020

@DustinCampbell -- thanks for the heads up. Will re-open, and will move to 5.0.x so that we can fix that on the first servicing release.

@safern safern reopened this Oct 28, 2020
@safern safern modified the milestones: 5.0.0, 5.0.x, 5.0.1 Oct 28, 2020
@safern
Copy link
Member

safern commented Oct 28, 2020

Also, ComponentDesigner is wrong...

@DustinCampbell
Copy link
Member Author

Thanks @safern!

Is ComponentDesigner wrong? It looks like DesignerAttribute uses IDesigner as a base type if the base type isn't specified.

@safern
Copy link
Member

safern commented Oct 28, 2020

You're right... somehow I can't read anymore and read IRootDesigner 😆

@ericstj
Copy link
Member

ericstj commented Oct 28, 2020

@DustinCampbell is this important to service in 5.0? Does it need to be serviced in the reference assemblies as well?

@DustinCampbell
Copy link
Member Author

I do think it's important to service in 5.0, but I don't think it's required in the reference assemblies? Typically, the designer acquires information like attributes from the runtime types or component instances.

@ericstj
Copy link
Member

ericstj commented Oct 28, 2020

Do you think you could share a repro that demonstrates the bug so that we can both validate the fix is working and determine if reference update is necessary?

I'm a bit surprised the designer has access to runtime assemblies, for instance in the case where the app is targeting net5.0 without a RID and tooling might be running on a different framework. Where would it find the runtime assembly?

@DustinCampbell
Copy link
Member Author

Do you think you could share a repro that demonstrates the bug so that we can both validate the fix is working and determine if reference update is necessary?

The repro would be to create an IComponent instance and call TypeDescriptor.CreateDesigner(...) with the base type as typeof(IDesigner) and then again with typeof(IRootDesigner). Today, both calls will return ComponentDesigner, but the second should return ComponentDocumentDesigner.

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 of IRootDesigner. 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

I'm a bit surprised the designer has access to runtime assemblies, for instance in the case where the app is targeting net5.0 without a RID and tooling might be running on a different framework. Where would it find the runtime assembly?

Everything is done via reflection using TypeDescriptor and PropertyDescriptor, 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.

@safern
Copy link
Member

safern commented Nov 18, 2020

Opening to track porting it to 5.0

@safern
Copy link
Member

safern commented Nov 24, 2020

Port is merged.

@safern safern closed this as completed Nov 24, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.