Domanda

Io sono alle prese con una situazione che mi è venuto di nuovo tempo e il tempo nuovo, ma io non sono sicuro che il modo in cui sto facendo delle cose è sbagliato o se ho potuto fare le cose in un modo diverso.

Un Esempio:

Ho un Windows Form che ha un DataGridView con alcuni metodi privati per eseguire la convalida del datagrid e interpretazione destro del mouse clic sul datagridview etc.Questo windows form è essenzialmente un "abstract" della classe e non viene creata un'istanza direttamente.

Ho quindi ereditare da questa classe di base e personalizzare in vari modi (modello di modello) ad es.definire le colonne del datagridview e particolari metodi di formattazione che sono specifici per le colonne etc.

Quando ho consumano queste classi la classe base di metodi pubblici formare la mia interfaccia e posso creare un'istanza di un tipo particolare di datagridview che voglio e manipolare attraverso l'interfaccia comune.Bella.

Il Problema:

Il problema principale è che in realtà non è possibile dichiarare un Windows Form classe astratta, senza causare la progettazione di Visual Studio per lanciare una traballante come è possibile creare un'istanza di queste classi astratte.

Alcune Soluzioni:

Al momento sto "implementazione" di quei metodi della classe base che voglio essere sostituito con:

    throw new NotSupportedException();

così almeno se mi dimentico di override di uno di questi metodi che costituiscono la mia interfaccia.Questo sembra piuttosto puzzolente a me, però, e non mi piace.

Un'altra soluzione che ho giocato è stato con l'ereditarietà del tutto, e di definire un'interfaccia (ad es.IMyDataGrid) e implementare che in ogni datagridview classe (una sorta di modello di strategia).Qui il problema però è che si perdono i vantaggi del codice ri-utilizzare eredità che dà senso che devi creare molte forme diverse, la goccia di un datagridview su di loro in modo efficace e copia e incolla il codice stesso in ciascuno di essi.Male.

C'è un modo migliore di cercare di raggiungere questo obiettivo?

È stato utile?

Soluzione

Ci sono molti modi per farlo, a seconda delle vostre esigenze.

  • Inserire il form contenuto in un controllo utente che implementa un'interfaccia personalizzata logica
  • Derivare classi DataGridView che implementa un'interfaccia personalizzata logica
  • Come accennato, l'utilizzo di un calcestruzzo di classe con virtual metodi invece di utilizzare un abstract classe
  • ...

Dovrete scegliere l'opzione che meglio si adatta alle vostre esigenze.Senza conoscere il dominio e specifiche in cui la tua domanda è stato chiesto, non penso che siamo in grado di dare un 100% risposta certa.

Altri suggerimenti

Check out questo metodo per sapere come creare i due attributi necessari.

È necessario il seguente attributo e il tipo di descrittore di classe (codice preso da UrbanPotato)

// Source : taken from http://www.urbanpotato.net/default.aspx/document/2001 Seem to be down
// Allow the designer to load abstract forms
namespace YourNamespace
{

    // Place this attribute on any abstract class where you want to declare
    // a concrete version of that class at design time.
    [AttributeUsage(AttributeTargets.Class)]
    public class ConcreteClassAttribute : Attribute
    {
        Type _concreteType;
        public ConcreteClassAttribute(Type concreteType)
        {
            _concreteType = concreteType;
        }

        public Type ConcreteType { get { return _concreteType; } }
    }

    // Here is our type description provider.  This is the same provider
    // as ConcreteClassProvider except that it uses the ConcreteClassAttribute
    // to find the concrete class.
    public class GeneralConcreteClassProvider : TypeDescriptionProvider
    {
        Type _abstractType;
        Type _concreteType;

        public GeneralConcreteClassProvider() : base(TypeDescriptor.GetProvider(typeof(Form))) { }

        // This method locates the abstract and concrete
        // types we should be returning.
        private void EnsureTypes(Type objectType)
        {
            if (_abstractType == null)
            {
                Type searchType = objectType;
                while (_abstractType == null && searchType != null && searchType != typeof(Object))
                {

                    foreach (ConcreteClassAttribute cca in searchType.GetCustomAttributes(typeof(ConcreteClassAttribute), false))
                    {
                        _abstractType = searchType;
                        _concreteType = cca.ConcreteType;
                        break;
                    }
                    searchType = searchType.BaseType;
                }

                if (_abstractType == null)
                {
                    // If this happens, it means that someone added
                    // this provider to a class but did not add
                    // a ConcreteTypeAttribute
                    throw new InvalidOperationException(string.Format("No ConcreteClassAttribute was found on {0} or any of its subtypes.", objectType));
                }
            }
        }

        // Tell anyone who reflects on us that the concrete form is the
        // form to reflect against, not the abstract form. This way, the
        // designer does not see an abstract class.
        public override Type GetReflectionType(Type objectType, object instance)
        {
            EnsureTypes(objectType);
            if (objectType == _abstractType)
            {
                return _concreteType;
            }
            return base.GetReflectionType(objectType, instance);
        }


        // If the designer tries to create an instance of AbstractForm, we override 
        // it here to create a concerete form instead.
        public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
        {
            EnsureTypes(objectType);
            if (objectType == _abstractType)
            {
                objectType = _concreteType;
            }

            return base.CreateInstance(provider, objectType, argTypes, args);
        }
    }
}

Assegnare la forma astratta, come questo:

[TypeDescriptionProvider(typeof(GeneralConcreteClassProvider))]
[ConcreteClass(typeof(MyAbstractConcreteForm))]
public abstract partial class MyAbstractForm : Form
{
}

Creare una nuova classe che eredita dalla forma astratta.Questa classe saranno istanziati da Visual Studio

public class MyAbstractConcreteForm: MyAbstractForm 
{
    public MyAbstractConcreteForm() : base() { }
}

Questo dovrebbe funzionare.

Ho lo stesso problema.
Questa pagina può aiutare, anche se è solo una soluzione: L'eredità di una Forma da una Classe Astratta (e che rende il Lavoro del Designer).

Non ho trovato alcuna soluzione migliore, ma sembra che non c'è.Così la Progettazione Windows Form ti costringe ad adattare il design di classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top