Reflection vs Factory pattern

#define _USE_FACTORY_
using System;
using System.Data;
using System.Reflection;
using System.Collections;
using System.Data.SqlClient;
namespace CSharpLab
{
 #region IStringIndexableData
 public interface IStringIndexableData
 {
  object this[string name]{get;}
 }
 #endregion
 #region StringIndexableWrapper
 /// 
 /// Wrapper per oggetti che si possono indicizzare con stringhe
 /// 
 public class StringIndexableWrapper: IStringIndexableData
 {
  //definisco la firma dell'indexer per stringa 
  delegate object StringIndexerHandler(string index);
  //definisco una cache dove salverò gli indexer per i vari tipi di oggetti
  //in modo da evitare la fase di discovery via reflection se già eseguita
  readonly static Hashtable indexersCache = new Hashtable();
  //handler all'indexer
  StringIndexerHandler indexerHandler;
  #region Constructors
  public StringIndexableWrapper(object stringIndexableObject)
  {
   //Ho già il methodinfo dell'indexer?
   Type stringIndexableObjectType = stringIndexableObject.GetType();
   MethodInfo indexerMethod = (MethodInfo) indexersCache[stringIndexableObjectType];
   if(indexerMethod == null)
   {
    //Fase di discovery...
    #region Finding string indexer   
    foreach(MemberInfo m in stringIndexableObjectType.GetDefaultMembers())
    {
     if(m is PropertyInfo)
     {
      PropertyInfo p = (PropertyInfo)m;
      ParameterInfo[] parameters =  p.GetIndexParameters();
      if(parameters.Length == 1)
      {
       ParameterInfo indexParam = parameters[0];
       if(indexParam.ParameterType == typeof(string))
       {
        indexerMethod = p.GetGetMethod();
        break;
       }
      }
     }
    }
    #endregion
    //l'oggetto non è indicizzabile per stringa
    if(indexerMethod == null)
     throw new ArgumentException("Object is not string indexable.", "stringIndexableObject");
   
    //salvo l'indexer nella cache
    indexersCache[stringIndexableObjectType] = indexerMethod;
   }
   //Costruisco handler all'indexer.
   //Perchè l'overload che accetta il methodInfo è valido solo per i metodi statici?
   //Devo necessariamente usare overload che usa nome del metodo anche se conosco methodInfo?
   indexerHandler =
    (StringIndexerHandler)Delegate.CreateDelegate(
     typeof(StringIndexerHandler), 
     stringIndexableObject, 
     indexerMethod.Name);
  }
  #endregion
  #region IStringIndexableData Members
  public object this[string s]
  {
   get
   {
    return indexerHandler(s);
   }
  }
  #endregion
 }
 #endregion
 
#region StringIndexableDataFactory
 public class StringIndexableDataRecord: IStringIndexableData
 {
  #region Fields
  private IDataRecord dataRecord;
  #endregion
  #region Constructors
  public StringIndexableDataRecord(IDataRecord dataRecord)
  {
   this.dataRecord = dataRecord;
  }
  #endregion
  #region IStringIndexableData Members
  public object this[string name]
  {
   get
   {
    return this.dataRecord[name];
   }
  }
  #endregion
 }
 public class StringIndexableDataRow: IStringIndexableData
 {
  #region Fields
  private DataRow dataRow;
  #endregion
  #region Constructors
  public StringIndexableDataRow(DataRow dataRow)
  {
   this.dataRow = dataRow;
  }
  #endregion
  #region IStringIndexableData Members
  public object this[string name]
  {
   get
   {
    return this.dataRow[name];
   }
  }
  #endregion
 }
 public class StringIndexableDataRowView: IStringIndexableData
 {
  #region Fields
  private DataRowView dataRowView;
  #endregion
  #region Constructors
  public StringIndexableDataRowView(DataRowView dataRowView)
  {
   this.dataRowView = dataRowView;
  }
  #endregion
  #region IStringIndexableData Members
  public object this[string name]
  {
   get
   {
    return this.dataRowView[name];
   }
  }
  #endregion
 }
 public class StringIndexableDataFactory
 {
  #region CreateStringIndexableData
  public static IStringIndexableData CreateStringIndexableData(IDataRecord record)
  {
   return new StringIndexableDataRecord(record);
  }
  public static IStringIndexableData CreateStringIndexableData(DataRow row)
  {
   return new StringIndexableDataRow(row);
  }
  public static IStringIndexableData CreateStringIndexableData(DataRowView row)
  {
   return new StringIndexableDataRowView(row);
  }
  #endregion
 }
 #endregion
 public class IndexerTest
 {
  public static void DoTest()
  {
   string sql = "SELECT * FROM Customers";
   using(SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;Data Source=(local)"))
   {
    connection.Open();
    //... uso la datatable
    SqlDataAdapter adp = new SqlDataAdapter(sql, connection);
    DataTable dt = new DataTable();
    adp.Fill(dt);
    
    foreach(DataRow row in dt.Rows)
    {
#if _USE_FACTORY_
     IStringIndexableData si = StringIndexableDataFactory.CreateStringIndexableData(row);
#else
     StringIndexableWrapper si = new StringIndexableWrapper(row);
#endif     
     Print(si);
    }
    //... uso la dataview
    DataView view = dt.DefaultView;
    foreach(DataRowView rowView in view)
    {
#if _USE_FACTORY_
     IStringIndexableData si = StringIndexableDataFactory.CreateStringIndexableData(rowView);
#else
     StringIndexableWrapper si = new StringIndexableWrapper(rowView);
#endif         
     Print(si);
    }
    //... uso il datareader
    SqlCommand cmd = new SqlCommand(sql, connection);
    SqlDataReader r = cmd.ExecuteReader();
    while(r.Read())
    {
#if _USE_FACTORY_
     IStringIndexableData si = StringIndexableDataFactory.CreateStringIndexableData(r);
#else
     StringIndexableWrapper si = new StringIndexableWrapper(r);
#endif     
     Print(si);
    }
   }
  }
  
  private static void Print(IStringIndexableData si)
  {
   Console.WriteLine(si["CompanyName"]);
  }
 }   
}

posted @ sabato 19 marzo 2005 19:42

Print
Comments have been closed on this topic.
«dicembre»
domlunmarmergiovensab
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234