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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:07:32  来源:igfitidea点击:

The designer must create an instance of...cannot because the type is declared abstract

c#.netwinformsabstract

提问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. Formitself 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 debugaround 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.

您将在设计(调试)和构建(发布)时获得完整的设计器支持和真正的抽象基类,因为每次它最终都会使用您的抽象基类。

The full explanation and answer is here

完整的解释和答案在这里

回答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.

我不需要将它添加到所有派生类中,但在您的情况下您可能需要这样做。