Abstract generic UserControl inheritance in Visual

2019-01-28 08:15发布

问题:

In one of my projects I'm using an abstract UserControl. To be able to design this control in Visual Studio I'm using the code proposed in this answer. Now I want to use this with another abstract UserControl which is also generic. But if I do

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<MyBaseControl<T>, UserControl>))]

I'm getting the compiler error

CS0416: an attribute argument cannot use type parameters

Removing the type parameter obviously doesn't compile either.

I can't derive MyBaseControl from a non generic base class because it already derives from an generic base class, so I tried decorating it with an interface and use it like so:

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<IMyBaseControl, UserControl>))]

This does compile but when I open the the design view my control doesn't get rendered, instead I get the error

The number of generic arguments provided doesn't equal the arity of the generic type definition.

Is there a way to solve this?

回答1:

I suppose you have a control AbstractGenericBase<T> : GenericBase<T> which GenericBase<T> is a control having such definition: GenericBase<T>: UserControl.

So if you want to show AbstractGenericBase<T> in designer, you can use this code:

using System.ComponentModel;
using System.Windows.Forms;

#if DEBUG
public abstract partial class AbstractGenericBase<T> : NonGenericBase
#else
public partial class AbstractGenericBase<T> : GenericBase<T>
#endif
{
    public AbstractGenericBase()
    {
        InitializeComponent();
    }
}
#if DEBUG
public class NonGenericBase : GenericBase<object> { }
#endif

Note

  • The goal is showing this class in designer:
    public abstract partial class AbstractGenericBase<T> : GenericBase<T>
  • If T has some type constraints, instead of object in GenericBase<object> use a Dummy which satisfies the generic constraints.
  • The solution is based on this fact: When the designer wants to show your control in design surface, it tries to create an instance of base class of your control. When the base class of your control is a generic class the designer doesn't know how to create an instance of base class.
    In above solution, for design-time support, we said to designer the base for our control is NonGenericBase, but for run-time, we keep GenericBase<T> as base class of our control.