Publié mardi 28 octobre 2008 23:01 par Luke77

MappingAttribute - Part II

Maintenant qu'il est possible de tagger les champs ou propriétées de notre classe, nous allons nous attaquer au code qui va nous permettre de lire ces informations afin de préparer le mapping.

Pour cela nous allons faire une première classe FieldMapped qui va définir chacun des mapping :

   1: internal class FieldMapped
   2: {
   3:     public MappingAttribute MappingAttribute;
   4:     public FieldInfo Field;
   5:     public PropertyInfo Property;
   6:  
   7:     public FieldMapped(MappingAttribute mappingAttribute, FieldInfo field, PropertyInfo property)
   8:     {
   9:         MappingAttribute = mappingAttribute;
  10:         Field = field;
  11:         Property = property;
  12:     }
  13: }

On retrouve ici le MappingAttribute qui aura été ajouté à la classe ainsi que le Field ou la Property sur lequel le MappingAttribute est appliqué. Voyons maintenant comment remplir cette classe. Ce sera le rôle de la classe BaseMapper<E> où E sera la classe qui devra être mappée. Sans plus attendre voilà le code :

   1: public abstract class BaseMapper<E>
   2: {
   3:     #region Protected Members
   4:  
   5:     protected Dictionary<string, FieldMapped> _specificMapping;
   6:  
   7:     #endregion
   8:  
   9:     #region Public Methods
  10:  
  11:     public virtual void InitializeMapping()
  12:     {
  13:         if (_specificMapping == null)
  14:         {
  15:             _specificMapping = new Dictionary<string, FieldMapped>();
  16:  
  17:             List<FieldInfo> fields = new List<FieldInfo>();
  18:             List<PropertyInfo> properties = new List<PropertyInfo>();
  19:  
  20:             Type type = typeof(E);
  21:  
  22:             while (type != typeof(object))
  23:             {
  24:                 fields.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance));
  25:                 properties.AddRange(type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance));
  26:                 type = type.BaseType;
  27:             }
  28:  
  29:  
  30:             for (int j = 0; j < fields.Count; j++)
  31:             {
  32:                 MappingAttribute[] attributes = (MappingAttribute[])fields[j].GetCustomAttributes(typeof(MappingAttribute), true);
  33:                 if (attributes != null && attributes.Length > 0)
  34:                 {
  35:                     if (_specificMapping.ContainsKey(attributes[0].ColumnName))
  36:                     {
  37:                         throw new ApplicationException("The column name is already mapped");
  38:                     }
  39:                     _specificMapping.Add(attributes[0].ColumnName, new FieldMapped(attributes[0], fields[j], null));
  40:                 }
  41:             }
  42:  
  43:             for (int j = 0; j < properties.Count; j++)
  44:             {
  45:                 MappingAttribute[] attributes = (MappingAttribute[])properties[j].GetCustomAttributes(typeof(MappingAttribute), true);
  46:                 if (attributes != null && attributes.Length > 0)
  47:                 {
  48:                     if (_specificMapping.ContainsKey(attributes[0].ColumnName))
  49:                     {
  50:                         throw new ApplicationException("The column name is already mapped");
  51:                     }
  52:                     _specificMapping.Add(attributes[0].ColumnName, new FieldMapped(attributes[0], null, properties[j]));
  53:                 }
  54:             }
  55:         }
  56:     }
  57:  
  58:     public abstract ulong Map(E entity, SqlDataReader reader);
  59:  
  60:     #endregion
  61: }

Je pense que le code parle pour lui-même mais grosso modo, qu'est-ce que l'on fait ? Tout d'abord on récupère l'ensemble des Fields et des Properties au sein du type de notre objet ainsi que sur tous les types dont il dérive (ligne 20 à 27). De tous ces fields/properties on recherche tous ceux qui ont attribut du type MappingAttribute et on rajoute une nouvelle instance de FieldMapped dans un dictionnaire indexé sur le nom de la colonne afin d'accroître la vitesse lorsque l'on fera le mapping.

 

Voilà pour cette deuxième partie de l'article. Dans la prochaine partie, on effectuera le mapping à proprement parler à l'aide de Reflection pour comprendre exactement ce que l'on veut obtenir, et on terminera par un dernier article plus complexe où de l'IL sera généré afin d'augmenter les performances.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Les 10 derniers blogs postés

- [SharePoint] Les sessions TechDays 2012… par Le blog de Patrick [MVP SharePoint] le il y a 3 heures et 49 minutes

- TechDays Paris 2012 : Session pleinière jour 3 par Blog Technique de Romelard Fabrice le 02-09-2012, 11:01

- Mishra Reader : un lecteur RSS très Zune Style en Open Source ! par Cyril Sansus le 02-09-2012, 08:28

- [framework 4] Les Tasks et le Thread UI par Fathi Bellahcene le 02-09-2012, 00:33

- Workflow Foundation 3 a un pied dans la tombe par Blog de Jérémy Jeanson le 02-08-2012, 22:15

- TechDays Paris 2012 : Nouvelles tendances du poste de travail - Bring Your own PC par Blog Technique de Romelard Fabrice le 02-08-2012, 19:42

- TechDays Paris 2012 : System Center Service Manager 2012 Vue d’ensemble par Blog Technique de Romelard Fabrice le 02-08-2012, 17:32

- TechDays Paris 2012 : Pleinière second jour par Blog Technique de Romelard Fabrice le 02-08-2012, 16:23

- TechDays Paris 2012 : Retour d'expérience sur la mise en place d'un Cloud Privé par Blog Technique de Romelard Fabrice le 02-08-2012, 16:04

- TechDays Paris 2012 : Comment SharePoint a sauvé mes TechDays par Blog Technique de Romelard Fabrice le 02-07-2012, 23:59