none
Probleme bei der Deklaration einer Schnittstelle mit Generics RRS feed

  • Frage

  • Hallo

    Ich habe ein Problem bei der Deklaration einer Schnittstelle – in Verbindung mit Generics. Folgendes Szenario möchte ich abdecken –

    Es gibt verschiedene Daten-SuchMasken – die alle von einer BaseSuchMasken-Klasse ableiten; von jeder SuchMaske kann immer der ausgewählte PrimaryKey des Datensatzes zurückgegeben werden an den Aufrufer; jetzt habe ich das Problem, dass ich einmal <GUID> als Prim.Key haben, und dann wieder <int>.

    Ich wollte das sauber lösen, indem ich eine Schnittstelle deklariere mit einer Methode wo der Rückgabe-Parameter als Generic deklariert wird – diese Schnittstelle sollte in die BaseSuchMasken-Klasse.

    Ich schaffe es aber leider nicht, die Schnittstelle bei der Base-Klasse richtig einzufügen. Ich kann es derzeit in den einzelnen abgeleiteten Klassen………aber dann muss ich erst recht  wieder die Methode jedes mal implementieren

    public partial class FormSearchLeistungen : PhysioApplication.FormSearchBase, ISearchSelectedPrimaryKey<int>
    {
    …
    …
    
        #region ISearchSelectedPrimaryKey<int> Members
    
        public int GetSelectedPrimaryKey()
        {
          int foundPrimKey = Convert.ToInt32(gridView.GetRowCellValue(gridView.FocusedRowHandle, gridView.Columns["PrimaryKey"]));
          return foundPrimKey;
        }
    
        #endregion
    
    
    }
     
    

    Wie kann ich das Ganze in die Base-Klasse geben, so dass ISearchSelectedPrimaryKey als Generic fungiert, und die GetSelectedPrimKey()-Methode einen Generic zurückgibt ???

    Kann mir dazu bitte jemand weiterhelfen ?

    Vielen Dank & schönen Gruß

    Michael

    Mittwoch, 11. August 2010 09:45

Antworten

  • Hallo Michael,

    Wäre die Idee von mir nicht die leichtere Lösung - wenn das mit dem null-Problem gelöst wäre ?? Hast Du vielleicht auch einen Rat bez. der null-Problematik?

    Es macht natürlich keinen Sinn, eine Schnittstelle zu implementieren, die nicht gebraucht wird.

    Die Idee mit der generischen Methode vereinfacht natürlich das Ganze etwas (aber Null zurückzugeben scheint mir keine gute Idee zu sein, dann schon eher default(T) da man nicht wissen kann, ob T ein Referenztyp oder ein Werttyp ist). Genaugenommen, würde ich diese ganze Funktionalität aus dem Form-Objekt herausnehmen und in eine separate Klasse kapseln, die ich dann mit der Form- oder DataGridView- oder BindingSource-Instanz konfigurieren kann.

    Gruß
    Marcel

    • Als Antwort markiert M.Erlinger Mittwoch, 11. August 2010 15:08
    Mittwoch, 11. August 2010 15:01
    Moderator

Alle Antworten

  • Hallo Michael,

    Falls ich Dich richtig verstehe, könntest Du in etwa so vorgehen:

    public interface ISearchSelectedPrimaryKey<T>
    {
      T GetSelectedPrimaryKey();
    }
    
    public class FormSearchBase<T> : ISearchSelectedPrimaryKey<T> 
    {
      #region ISearchSelectedPrimaryKey<T> Member
      public T GetSelectedPrimaryKey()
      {
        T foundPrimKey = (T) GetPrimaryKeyValue();
        return foundPrimKey;
      }
      #endregion
    }
    
    

    Um mehr zu sagen, fehlt mir das größere Bild.


    Gruß
    Marcel

    Mittwoch, 11. August 2010 12:39
    Moderator
  • Hallo

    Danke für Deine Rückmeldung. Ich habe Deinen Code natürlich gleich probiert - und ich war auch schon soweit einmal.

    Das Problem liegt daran, sobald ich den Code anpasse - auch so wie Dein Vorschlag aussieht - funktioniert die WinFormKlasse nicht mehr. Er kennt dann zum Beispiel "InitializeComponent()" nicht mehr - und bei allen Controls die im Source angesprochen werden gibt es einen CompilerFehler.

    Liegt das vielleicht an der WinForm-Klasse in Verbindung mit Generics ?

    Danke & schönen Gruß

    Michael

    Mittwoch, 11. August 2010 12:45
  • Hallo Michael,

    > Liegt das vielleicht an der WinForm-Klasse in Verbindung mit Generics ?

    Ja. Es hat aber nicht direkt mit Windows Forms zu tun, sondern mit den Limitierungen des Windows Forms Designers in Bezug auf Generics. Du kannst Dir dennoch behelfen, indem Du eine Klasse von FormSearchBase<T> ableitest, z.B. FormSearchIntBase : FormSearchBase<int>, und die vom Designer zu bearbeitende Form dann von MyFormSearchIntBase ableitest, z.B. Form1 : FormSearchIntBase. Natürlich muss dabei die Basisklasse FormSearchBase<T> von System.Windows.Forms.Form abgeleitet sein, also: public class FormSearchBase<T> : Form, ISearchSelectedPrimaryKey<T>.

    Gruß
    Marcel

    Mittwoch, 11. August 2010 13:35
    Moderator
  • Hallo Marcel

    eigentlich bin ich gerade d'rauf gekommen, dass ich es viel einfacher lösen könnte - ohne Interface, nur die Methode in der BasisKlasse "FormSearchBase" als generische Methode implementieren......

    public T getSelectedPrimKey<T>()
    {
          if (gridView.RowCount > 0)
          {
            T primaryKey = (T)gridView.GetRowCellValue(gridView.FocusedRowHandle, gridView.Columns["PrimaryKey"]);
            return primaryKey;
          }
          else
          {
            // do something.......
            return null;
          }
    } 
    

    Nur gibt es da Probleme mit dem "null"-Return. Wenn ich die Methoden-Deklaration auf

    public Nullable<T> getSelectedPrimKey<T>()
    {
    } 
    

    ändere, dann kommt auch eine Compiler-Fehlermeldung "The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method "

     

    Wäre die Idee von mir nicht die leichtere Lösung - wenn das mit dem null-Problem gelöst wäre ?? Hast Du vielleicht auch einen Rat bez. der null-Problematik?

    Danke schon mal und schönen Gruß

    Michael

    Mittwoch, 11. August 2010 14:41
  • Hallo Michael,

    Wäre die Idee von mir nicht die leichtere Lösung - wenn das mit dem null-Problem gelöst wäre ?? Hast Du vielleicht auch einen Rat bez. der null-Problematik?

    Es macht natürlich keinen Sinn, eine Schnittstelle zu implementieren, die nicht gebraucht wird.

    Die Idee mit der generischen Methode vereinfacht natürlich das Ganze etwas (aber Null zurückzugeben scheint mir keine gute Idee zu sein, dann schon eher default(T) da man nicht wissen kann, ob T ein Referenztyp oder ein Werttyp ist). Genaugenommen, würde ich diese ganze Funktionalität aus dem Form-Objekt herausnehmen und in eine separate Klasse kapseln, die ich dann mit der Form- oder DataGridView- oder BindingSource-Instanz konfigurieren kann.

    Gruß
    Marcel

    • Als Antwort markiert M.Erlinger Mittwoch, 11. August 2010 15:08
    Mittwoch, 11. August 2010 15:01
    Moderator
  • Danke - hast mir sehr weitergeholfen!!

    Schönen Gruß

    Michael

    Mittwoch, 11. August 2010 15:08