Visual Studio设计器中的抽象UserControl继承

asm*_*smo 31 c# user-controls abstract-class winforms

abstract class CustomControl : UserControl 
{
    protected abstract int DoStuff();
}

class DetailControl : CustomControl
{
    protected override int DoStuff()
    { 
        // do stuff
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在表单中删除了一个DetailControl.它在运行时正确呈现,但设计器显示错误并且无法打开,因为基本用户控件是抽象的.

目前,我正在考虑以下补丁,这对我来说似乎很不对,因为我希望子类被强制实现该方法.

class CustomControl : UserControl 
{
    protected virtual int DoStuff()
    {
        throw new InvalidOperationException("This method must be overriden.");
    }
}

class DetailControl : CustomControl
{
    protected override int DoStuff()
    { 
        // do stuff
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都有更好的想法如何解决这个问题?

juc*_*rdi 48

我们想要什么

首先,让我们定义最终类和基本抽象类.

public class MyControl : AbstractControl
...
public abstract class AbstractControl : UserControl // Also works for Form
...
Run Code Online (Sandbox Code Playgroud)

现在我们所需要的只是一个描述提供者.

public class AbstractControlDescriptionProvider<TAbstract, TBase> : TypeDescriptionProvider
{
    public AbstractControlDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(TAbstract)))
    {
    }

    public override Type GetReflectionType(Type objectType, object instance)
    {
        if (objectType == typeof(TAbstract))
            return typeof(TBase);

        return base.GetReflectionType(objectType, instance);
    }

    public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
    {
        if (objectType == typeof(TAbstract))
            objectType = typeof(TBase);

        return base.CreateInstance(provider, objectType, argTypes, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我们将一个TypeDescriptionProvider属性应用于Abstract控件.

[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<AbstractControl, UserControl>))]
public abstract class AbstractControl : UserControl
...
Run Code Online (Sandbox Code Playgroud)

就是这样.无需中间控制.

并且提供者类可以在同一解决方案中应用于我们想要的尽可能多的抽象基础.

  • 这对我有用,虽然在我的情况下我在我的具体子类和`UserControl`之间有两个级别的`abstract`类.对于两个`abstract`类,我需要使用`TBase`提供`TypeDescriptionProvider`的`UserControl`.我将`TBase`重命名为`TFirstConcreteBase`,以便明确清楚地跟随我.我原本希望两个原始的`TBase`声明能够连在一起,以获得正确的具体基础,但事实并非如此.谢谢你的帮助,@ Juan. (3认同)
  • 很高兴我能帮助@JMD (2认同)
  • 您还需要重新编译您的projekt并关闭Visual Studio以使设计器消息消失 (2认同)

Nic*_*oiu 19

您可以使用TypeDescriptionProviderAttribute为抽象基类提供具体的设计时实现.有关详细信息,请参见http://wonkitect.wordpress.com/2008/06/20/using-visual-studio-whidbey-to-design-abstract-forms/.


Gui*_*rez 6

解决此问题的另一种方法是使用预处理指令.

#if DEBUG
  public class UserControlAdmonEntidad : UserControl, IAdmonEntidad
#else
  public abstract class UserControlAdmonEntidad : UserControl, IAdmonEntidad
#endif
  {
    ...
    #if DEBUG
    public virtual object DoSomething()
    {
        throw new NotImplementedException("This method must be implemented!!!");
    }
    #else
    public abstract object DoSomething();
    #endif

    ...
  }
Run Code Online (Sandbox Code Playgroud)

有关此主题的更多信息,请参阅此链接:从抽象类继承表单(并使其在Designer中工作)

在这个MSDN论坛帖子中也提到了相同的解决方案,简单明了:UserControl,Inherited Control,Abstract class,(C#)

也许不是更清洁的解决方案,但它仍然是我找到的最短的解决方案.