2009-05-12 19 views
1

Ich habe den folgenden Code, wo ich versuche, eine generische Sammlung für die Objekte in meinem DAL (nur eine Übung, nicht eigentlich Produktionscode) zu erstellen. Mein Problem ist, dass ich die Read-Methode des Typs verwenden möchte (die Teil einer Schnittstelle ist, die die Klassen implementieren).Generische Sammlung wird vom generischen Typ geladen

Ich kann kein new T erstellen, also habe ich keine Instanz des Objekts, mit zu arbeiten, und ich kann es nicht als Basistyp deklarieren, da ich die vom Kind des Basisobjekts angegebene Lese-Methode brauche.

Ist das wirklich möglich oder bin ich am falschen Baum?

public class ItemDictionary<T> where T : ILoadable, DataItem 
{ 

    public void Load() 
    { 
     using (IDataReader reader = SqlHelper.ExecuteReader(_connection, CommandType.StoredProcedure, _proc)) { 
      Read(reader); 
     } 
    } 

    bool Read(IDataReader reader) 
    { 
     while (reader.Read) 
     { 
      T item = default(T);   //Here be the problem 

      if (item.Read(reader)) 
      { 
       this.Add(item.Guid, item); 
      } 
     } 

     return true; 
    } 

} 

public class ExampleObject : DataItem, ILoadable 
{ 

    bool Read(IDataReader reader) 
    { 
     _var1 = reader.getString(0); 
     _var2 = reader.getString(1); 
     _var3 = reader.getString(2); 

     return true; 
    } 
} 

Antwort

3

Können Sie nicht über einen Standardkonstruktor von der Art (en) haben durch die Sammlung statt und fügen Sie die neue() Richtlinie über die where T: Richtlinie?

public class ItemDictionary<T> where T : ILoadable, DataItem, new() 

und dann: -

T item = new T(); 
+0

Genau das, was ich vermisste! Es funktionierte sogar in VB.net :) – Pondidum

1

Es ist mir nicht klar, warum Sie nicht new T() verwenden können (mit einer entsprechenden Einschränkung für T). Es ist mir auch nicht klar, warum Sie eine explizite Schnittstellenimplementierung verwenden und warum Ihre ILoadable Schnittstelle eine Methode namens ILoadable hat, wohlgemerkt.

Ist das Problem, dass Sie nicht immer garantieren können, einen parameterlosen Konstruktor im Objekttyp zu haben? Wenn das der Fall ist, werden Sie sicherlich etwas Instanzen von T erstellen müssen. Vielleicht brauchen Sie eigentlich T von seinem Werk zu trennen, vielleicht mit einer anderen Schnittstelle:

public interface IFactory<T> 
{ 
    // Roughly matching your current API 
    bool TryRead(IDataReader reader, out T); 

    // Simpler if you can just throw an exception on error 
    T Read(IDataReader reader); 
} 

Dann können Sie einfach eine IFactory<T> Implementierung in Ihr ItemDictionary<T> Konstruktor übergeben.

+0

Sorry, konvertiert dieses Formular vb.net mit einem Online-Code-Konverter ... – Pondidum

Verwandte Themen