2017-11-22 4 views
0

Ich möchte in der Lage sein, ein Tupel an die folgende Methode zu übergeben, aber ich kann nicht, da ich es instanziieren muss.C#: Erzeuge ein Tupel von einem generischen Typ mit Reflektion

public List<T> Select<T>(string sql, DbCommand command) where T : new() 
    { 
     DbDataReader dataReader = null; 
     List<T> ls = new List<T>(); 
     Type tType = typeof(T); 
     T t; 
     PropertyInfo prop = null; 
     string[] propertiesNames = GetPropertiesNamesFromSQL(sql); 

     try 
     { 
      dataReader = command.ExecuteReader(); 
      if (dataReader == null || !dataReader.HasRows) return ls; 

      while (dataReader.Read()) 
      { 
       t = new T(); 

       for (int i = 0; i < dataReader.FieldCount; i++) 
       { 
        prop = tType.GetProperty(propertiesNames[i]); 

        prop.SetValue(t, dataReader.GetValue(i)); 
       } 

       ls.Add(t); 
      } 
     } 
     catch (Exception){ } 
     finally 
     { 
      if (dataReader != null) dataReader.Close(); 
     } 

     return ls; 
    } 

Wie ich in den Kommentaren gesagt, ich versuche, mit einem nackten Knochen ORM zu bauen, bin ich in der Mapping-Objekten Teil nur interessiert. Es funktioniert so, wie es ist, jedoch wäre es manchmal praktisch, wenn schnelle Abfragen ein Tuple anstelle einer vollständigen Klasse übergeben können.

Gibt es eine Lösung?

+0

Nicht sicher, dass ich verstehe ... Warum können Sie die Tuple nicht als Parameter übergeben? – Ruslan

+2

Um sicherzustellen, dass dies kein XY-Problem ist (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), können Sie einen Schritt zurücktreten und erklären, warum Sie diesen Code benötigen? – mjwills

+0

Wenn Sie sagen, übergeben Sie ein Tupel, fragen Sie, ob Sie es als generischen Parameter verwenden? Was du als Tuple nicht tun kannst, ist eine Struktur, keine Klasse. Es wäre auch nicht sinnvoll mit dem inneren Code zu arbeiten, da ein Tuple keine Eigenschaft namens "ClientName" haben wird. Es sei denn, Sie sprechen über eine TupleClass (die ich ehrlich gesagt nicht untersucht habe) – d219

Antwort

0

Es funktioniert nicht so. Erstellen einer Methode, die alles aus einer Datenbank generiert, ist aus vielen Gründen keine gute Lösung.

Ein richtiger Weg, dies zu tun, wäre ein bisschen komplizierter. Ich denke, dass Sie eine Fabrik Schnittstelle benötigen, wie folgt aus:

public interface IMyFactory<T> where T : new() 
{ 
    T Create (string name); 
} 

dann ein Betonwerk:

public class MyFactory : IMyFactory<MyClient> 
{ 
    public MyClient Create (string name) 
    { 
     var t = new MyClient(); 
     t.ClientName = name; 
     return t; 
    } 
} 

und geben es dann auf Ihre Methode wie:

public List<T> SelectFromDataBase<T> (IMyFactory<T> factory) where T : new() 
{ 
    var ls = new List<T>(); 

    // highly simplified here 
    T t = factory.Create("Mr Smith"); 

    ls.Add(t); 

    return ls;   
} 

Dann könnten Sie rufen Ihre Methode als:

var myList = SelectFromDataBase(new MyFactory()); 

Damit transformieren Sie Daten aus der Datenbank in ein Objekt, das von der Objekterstellungslogik getrennt ist.

Verwandte Themen