2009-05-27 6 views
0

Ich habe die folgende Methode:generische Funktion für eine vereinfachte Code

private JobCard PopulateObject(JobCard jc, DataRow dataRow) 
{ 

    PropertyInfo[] proplist = jc.GetType().GetProperties(); 

    foreach (PropertyInfo propertyitem in proplist) 
    { 
     if (propertyitem.Name != "") 
      if (propertyitem.PropertyType.BaseType.Namespace == "System") 
      { 
       propertyitem.SetValue(jc, dataRow[propertyitem.Name], null);     
      } 
      else 
      { 
       string typename = propertyitem.ToString().Replace("Pss.Common.Mia.", ""); 
       int i = typename.IndexOf("Base"); 
       typename = typename.Substring(0, i); 
       Type type = propertyitem.PropertyType; 

       switch (typename) 
       { 
        case "Customer": 
         propertyitem.SetValue(jc, PopulateCustomerObject(propertyitem, dataRow, type), null); 
         break; 
        case "Meter": 
         propertyitem.SetValue(jc, PopulateMeterObject(propertyitem, dataRow, type), null); 
         break; 
        case "TimeSheet": 
         propertyitem.SetValue(jc, PopulateTimeSheetObject(propertyitem, dataRow, type), null); 
         break; 
       } 
      } 
    } 

    return jc; 

} 

Das obige Verfahren nennt diese:

private Customer PopulateCustomerObject(object o, DataRow dataRow, Type type) 
    { 
      IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); 
     PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 

     Customer c = new Customer(); 

    Guid customerGuid = new Guid(dataRow["AddressId"].ToString()); 
    string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View; 

    string query = string.Format("select * from {0} where id = '{1}'", view, customerGuid); 

    c = DataAccess.Retriever.Retrieve<Customer>(query); 

    return c; 
} 


private Address PopulateAddressObject(object o, DataRow dataRow, Type type) 
{ 
    IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); 
    PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 

    Address a = new Address(); 

    Guid AddressGuid = new Guid(dataRow["PhysicalAddressId"].ToString()); 
    string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View; 

    string query = string.Format("select * from {0} where id = '{1}'", view, AddressGuid); 

    a = DataAccess.Retriever.Retrieve<Address>(query); 
    return a; 
} 

private Meter PopulateMeterObject(object o, DataRow dataRow, Type type) 
{ 

    IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); 
    PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 

    Meter m = new Meter(); 

    Guid meterGuid = new Guid(dataRow["MeterId"].ToString()); 
    string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View; 

    string query = string.Format("select * from {0} where id = '{1}'", view, meterGuid); 

    m = DataAccess.Retriever.Retrieve<Meter>(query); 
    return m; 
} 

, die ich sehen kann, am besten durch ein gattungsgemäßes Verfahren würde ersetzt werden, aber wie?

Ich sehe nicht, wie

Customer c = new Customer(); 
Address a = new Address(); 
Meter m = new Meter(); 
TimeSheet t = new TimeSheet(); 

mit 1 generic Linie zu ersetzen, und auch

c = DataAccess.Retriever.Retrieve<Customer>(query); 
a = DataAccess.Retriever.Retrieve<Address>(query); 
m = DataAccess.Retriever.Retrieve<Meter>(query); 
t = DataAccess.Retriever.Retrieve<TimeSheet>(query); 

Ich kann nicht Retriever.Retrieve ändern. Es wird erklärt, wie

public static T Retrieve<T>(string query) 
      where T : IDataStorable 
     { 
      return Retrieve<T>(query, new IDbDataParameter[0], string.Empty); 
     } 
+0

Bitte klären ein paar Dinge; Es ist nicht klar, wie (wenn?) Sie "proplist" oder "o" in den "Populate" -Methoden verwenden; ist 'Typ' Kunde/Adresse usw.? Warum die komplizierte CreateInstanceAndUnwrap? Auch - Vorsicht SQL Injection ... –

+0

Auch: propertyitem; du gibst das als 'o' ein und (separat) rufst propertyitem.ToString() auf - ich glaube nicht, dass beides eine gute Idee ist ... was versucht es zu tun? –

+0

ein paar Dinge klären; früh morgens, Kaffee hat noch nicht getreten - aber die Proplist ist unnötig, kopiert und eingefügt von früheren versuchen dieses Problem. Daher ist CreateInstanceAndUnwrap auch redundant. Kunde, Adresse, Zähler und Arbeitszeittabelle sind Typen. Die Hierarchie ist: JobCard enthält TimeSheet, Neter, Kunde (die Adresse enthält) SQL-Injection kein Problem, wie diese Methoden über validierte WM5 App über Webservice – callisto

Antwort

1

all dies scheint ein wenig dunkel und komplex, aber Ihre Frage direkt zu beantworten - um Ihre PopulateAddressObject Funktion genericise Sie etwas tun können:

private TPopulateAddressObject(object o, DataRow dataRow, Type type, string idColumnName) where T : IDataStorable, new() 
{ 
    IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); 
    PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 

    T obj = new T(); 

    Guid id = new Guid(dataRow[idColumnName].ToString()); 
    string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View; 

    string query = string.Format("select * from {0} where id = '{1}'", view, id); 

    obj = DataAccess.Retriever.Retrieve<T>(query); 
    return obj; 
} 
+0

aufgerufen werden Beachten Sie, dass "Instanz", "Proplist" und "Obj" (von neuen T()) werden verworfen, ohne dass sie tatsächlich verwendet werden (ein Fehler im ursprünglichen Code) –

1

Es wird eine Menge Dinge in den Populate* Methoden, die Sie gerade nicht verwenden; zum Beispiel, verwenden Sie nicht wirklich das Objekt, das Sie verbringen viel Zeit ... und

Wie über das Hinzufügen einer PrimaryKey Eigenschaft [DBObjectRetrieveAttribute] (zu halten, um die abgebildeten DataRow Spalte), und so etwas wie:

private static T Populate<T>(DataRow dataRow) 
    where T : class, IDataStorable, new() 
{ 
    DBObjectRetrieveAttribute ora = 
     ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(typeof(T)); 
    string view = ora.View; 
    Guid pkid = new Guid(dataRow[ora.PrimaryKey].ToString()); 
    // beware SQL injection... 
    string query = string.Format("select * from {0} where id = '{1}'", 
     view, pkid); 

    return DataAccess.Retriever.Retrieve<T>(query); 
} 

Dann müssen die verschiedenen Eigenschaftstypen nicht mehr eingeschaltet werden; Sie können MakeGenericMethod verwenden:

object obj = MethodInfo mtd = typeof(SomeType).GetMethod("Populate", 
     BindingFlags.NonPublic | BindingFlags.Static) 
    .MakeGenericMethod(propertyitem.PropertyType) 
    .Invoke(null, new object[] {dataRow}); 
propertyitem.SetValue(jc, obj, null); 

Alternativ; übergeben Sie die ID in als Argument:

private static T Populate<T>(DataRow dataRow, string primaryKey) 
    where T : class, IDataStorable, new() 
{ 
    ... snip 
    Guid pkid = new Guid(dataRow[primaryKey].ToString()); 
    ... snip 
} 

Und so etwas wie:

object obj; 
if(type == typeof(Customer)) { 
    obj = Populate<Customer>(dataRow, "AddressId"); 
} else if (type == typeof(Meter)) { 
    obj = Populate<Meter>(dataRow, "MeterId"); 
} else if (...etc...) { 

} else { 
    throw new InvalidOperationException("Type is not supported: " + type.Name); 
} 
propertyitem.SetValue(jc, obj, null); 
+0

DBObjectRetrieveAttribute ora = ReflectionHelper.GetAttribute (typeof (T)); funktioniert nicht. :( T ist nicht dasselbe wie propertyitem.PropertyType T Name = "Kunde" aber propertyitem.PropertyType Name = "CustomerBase'1" – callisto

+0

Achja, aber etwas in diese Richtung, dann.Da CustomerBase1 nicht erwähnt wurde, konnte ich das nicht vorhersagen! –

Verwandte Themen