C# 设计者必须创建...的实例,因为该类型被声明为抽象的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/481305/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The designer must create an instance of...cannot because the type is declared abstract
提问by Malfist
Visual Studio complains: Warning 1 The designer must create an instance of type 'RentalEase.CustomBindingNavForm' but it cannot because the type is declared as abstract.
Visual Studio 抱怨:警告 1 设计器必须创建一个类型为“RentalEase.CustomBindingNavForm”的实例,但它不能,因为该类型被声明为抽象类型。
Visual Studio won't let me access the Designer for the form. The class already implements all abstract methods from the CustomBindingNavForm. CustomBindingNavForm provides some functions concrete and abstract.
Visual Studio 不允许我访问表单的设计器。该类已经实现了来自 CustomBindingNavForm 的所有抽象方法。CustomBindingNavForm 提供了一些具体和抽象的功能。
Is there a way around this?
有没有解决的办法?
Here is the class:
这是课程:
public abstract class CustomBindingNavForm : SingleInstanceForm {
//Flags for managing BindingSource
protected bool isNew = false;
protected bool isUpdating = false;
/// <summary>
/// This is so that when a new item is added, it sets isNew and firstPass to true. The Position Changed Event will look for
/// firstPass and if it is true set it to false. Then on the next pass, it will see it's false and set isNew to false.
/// This is needed because the Position Changed Event will fire when a new item is added.
/// </summary>
protected bool firstPass = false;
protected abstract bool validateInput();
protected abstract void saveToDatabase();
//manipulating binding
protected abstract void bindingSourceCancelResetCurrent();
protected abstract void bindingSourceRemoveCurrent();
protected abstract void bindingSourceMoveFirst();
protected abstract void bindingSourceMoveNext();
protected abstract void bindingSourceMoveLast();
protected abstract void bindingSourceMovePrevious();
protected abstract void bindingSourceAddNew();
public void bindingNavigatorMovePreviousItem_Click(object sender, EventArgs e) {
if (validateInput()) {
bindingSourceMovePrevious();
} else {
DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (cont == DialogResult.OK) {
if (isNew) {
bindingSourceRemoveCurrent();
isNew = false;
} else {
bindingSourceCancelResetCurrent();
bindingSourceMovePrevious();
}
}
}
}
public void bindingNavigatorAddNewItem_Click(object sender, EventArgs e) {
if (validateInput()) {
saveToDatabase();
bool temp = isUpdating;
isUpdating = true;
bindingSourceAddNew();
isUpdating = temp;
isNew = true;
firstPass = true;
} else {
DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (cont == DialogResult.OK) {
if (isNew) {
bindingSourceRemoveCurrent();
isNew = false;
} else {
bindingSourceCancelResetCurrent();
}
bool temp = isUpdating;
isUpdating = true;
bindingSourceAddNew();
isUpdating = temp;
isNew = true;
firstPass = true;
}
}
}
public void bindingNavigatorMoveFirstItem_Click(object sender, EventArgs e) {
if (validateInput()) {
bindingSourceMoveFirst();
} else {
DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (cont == DialogResult.OK) {
if (isNew) {
bindingSourceRemoveCurrent();
isNew = false;
} else {
bindingSourceCancelResetCurrent();
}
bindingSourceMoveFirst();
}
}
}
public void bindingNavigatorMoveNextItem_Click(object sender, EventArgs e) {
if (validateInput()) {
bindingSourceMoveNext();
} else {
DialogResult cont = MessageBox.Show(null, "There are errors in your data. Click Cancel to go back and fix them, or ok to continue. If you continue, changes will not be saved.", "Continue?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (cont == DialogResult.OK) {
if (isNew) {
bindingSourceRemoveCurrent();
isNew = false;
} else {
bindingSourceCancelResetCurrent();
}
bindingSourceMoveNext();
}
}
}
}
采纳答案by Allen Rice
I haven't seen the content at urban potato (its down) but Me and Smelchcame up with a solution. Form
itself inherits from an abstract class, sowhat they dont tell you is that its only the 1st level of inheritance that can't be abstract, the 2nd on down can.
我还没有看到城市土豆的内容(它下来),但我和Smelch想出了一个解决方案。 Form
本身继承自一个抽象类,所以他们没有告诉你的是,它只有第一级继承不能是抽象的,第二级可以。
From there its simply a matter of having an empty class in the middle and wrapping an #if debug
around the forms declaration and you're good to go. Just be sure to release in release mode and design in debug mode (which is very typical).
从那里开始,只需在中间有一个空类并#if debug
在表单声明周围包装一个,就可以了。只要确保在发布模式下发布并在调试模式下设计(这是非常典型的)。
You'll get full designer support and a real abstract base class at design (debug) and build (release) time because each time it ends up using your abstract base class.
您将在设计(调试)和构建(发布)时获得完整的设计器支持和真正的抽象基类,因为每次它最终都会使用您的抽象基类。
回答by statler
You can solve this using an attribute on your abstract class like the following
您可以使用抽象类上的属性来解决这个问题,如下所示
[TypeDescriptionProvider(typeof(AbstractControlDescriptionProvider<MyBaseFormEf, Form>))]
This will work for every case where you need it. The AbstractControlDescriptionProvider is below
这将适用于您需要的每种情况。AbstractControlDescriptionProvider 在下面
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);
}
}
回答by Kim
This worked for me with an abstract class inheriting a UserControl
这对继承 UserControl 的抽象类对我有用
public class AbstractCommunicatorProvider : TypeDescriptionProvider
{
public AbstractCommunicatorProvider(): base(TypeDescriptor.GetProvider(typeof(UserControl)))
{
}
public override Type GetReflectionType(Type objectType, object instance)
{
return typeof(UserControl);
}
public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
{
objectType = typeof(UserControl);
return base.CreateInstance(provider, objectType, argTypes, args);
}
}
[TypeDescriptionProvider(typeof(AbstractCommunicatorProvider))]
public abstract partial class SelectorBase : UserControl
{
///class contents
}
I didn't need to add this to all derived classes but in your situation you may need to.
我不需要将它添加到所有派生类中,但在您的情况下您可能需要这样做。