2009-05-27 14 views
0

私は、次の方法があります。汎用関数

私が見ることができる
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; 
} 

は最高の1つのジェネリックメソッドに置き換えられますが、どのよう:

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; 

} 

を上記の方法は、これらを呼び出しますか?

私はRetriever.Retrieveを変更することはできません1つの一般的なラインで

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

を交換する方法を見て、そしてまた

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

いけません。

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

いくつかのことを明確にしてください。 "Populate"メソッドで 'proplist'や' o'をどのように使うのかは明らかではありません。 'type'顧客/住所などですか?なぜ複雑なCreateInstanceAndUnwrapですか?また、SQLインジェクションに注意してください... –

+0

また:propertyitem;あなたは 'o'としてそれを渡し、(別に)propertyitem.ToString()を呼び出す - これはどちらかというと良い考えではないと思います...何をしようとしていますか? –

+0

はいくつかのことを明確にします。早起き、coffeはまだ蹴られていませんが、プロプリストはこの問題の以前の試行から不要で、コピーされ貼り付けられています。したがって、CreateInstanceAndUnwrapも冗長です。顧客、住所、メーター、およびタイムシートはタイプです。 JobCardにはTimeSheet、Neter、Customer(Addressを含む)のSQLインジェクションが含まれています。これらのメソッドは、Webサービス – callisto

答えて

1

このように宣言されましたあなたがちょうど使用しない方法の多くはPopulate*です。たとえば、あなたが実際には(マップされたDataRow列を保持する)[DBObjectRetrieveAttribute]PrimaryKeyプロパティを追加し、何かのようについて...あなたは時間作成の多くを費やす

どのようにオブジェクトを使用していない:

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); 
} 

異なるプロパティタイプをオンにする必要はありません。 MakeGenericMethod

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); 

代わりに使用することもできます。引数としてIDを渡す:

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

など、何かの操作を行います。

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

を介して検証されたWM5アプリケーションを介して呼び出されるため、問題はありません。 "instance"、 "proplist"、 "obj" ())はすべて実際に使用されずに破棄されます(元のコードの障害) –

1

があります:あなたはこのような何かを行うことができますPopulateAddressObject機能をgenericiseするために - すべてが少し曖昧で複雑なようだが、直接あなたの質問に答えるために

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

DBObjectRetrieveAttribute ora = ReflectionHelper.GetAttribute (typeof(T)); : Tはpropertyitem.PropertyTypeと同じではありません。 T Name = "Customer" but propertyitem.PropertyType Name = "CustomerBase'1" – callisto

+0

ああ、そうした行に沿って何かが起こります。CustomerBase1は言及されていないので、私はそれを予測できませんでした! –

関連する問題