2011-12-20 2 views
0

J'ai une classe auxiliaire de mappage de données qui utilise des génériques et des réflexions. Comme j'utilise la réflexion et les génériques dans ma classe d'aide, le code des opérations CRUD standard est identique dans tous mes objets métier (comme dans la méthode de classe Create(), donc j'essaie de utilisez une classe BusinessObject de base pour gérer les méthodes répétitives.Référencement d'un objet dérivé dans une classe de base

Je souhaite que la classe de base puisse appeler mes méthodes génériques DataUtils, qui acceptent par exemple une référence à l'objet d'objet métier dérivé pour remplir les paramètres SQL.

DataUtils.CreateParams attend un objet de type T et un booléen (indique insertion ou mise à jour). Je veux passer "ceci", représentant mon objet dérivé la classe de base, mais je reçois erreur de compilation "La meilleure correspondance surchargée contient des paramètres invalides." Si j'implémente Create() dans la classe dérivée et que je passe la méthode Create de la classe de base en référence à "this", cela fonctionne, mais j'implémente toujours toutes les méthodes CRUD, à l'identique, dans chaque objet métier classe. Je veux que la classe de base les gère.

Est-il possible qu'une classe de base appelle une méthode et transmette une référence à l'objet dérivé?

Voilà ma classe de base:

public abstract class BusinessObject<T> where T:new() 
{ 
    public BusinessObject() 
    { } 

    public Int64 Create() 
    { 
     DataUtils<T> dataUtils = new DataUtils<T>(); 
     string insertSql = dataUtils.GenerateInsertStatement(); 
     using (SqlConnection conn = dataUtils.SqlConnection) 
     using (SqlCommand command = new SqlCommand(insertSql, conn)) 
     { 
      conn.Open(); 

      //this line is the problem 
      command.Parameters.AddRange(dataUtils.CreateParams(obj, true)); 
      return (Int64)command.ExecuteScalar(); 

     } 
    } 
} 

}

Et une classe dérivée:

public class Activity: BusinessObject<Activity> 
{ 
    [DataFieldAttribute(IsIndentity=true, SqlDataType = SqlDbType.BigInt)] 
    public Int64 ActivityId{ get; set; } 
    ///...other mapped fields removed for brevity 

    public Activity() 
    { 
     ActivityId=0; 
    } 

    //I don't want to have to do this... 
    public Int64 Create() 
    { 

     return base.Create(this); 
    } 
+1

Ah, [le CRTP] (http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx) – SLaks

Répondre

2

Il suffit de jeter this à T:

dataUtils.CreateParams((T)this, true); 

Si vous créez un public class Evil : BusinessObject<Good>, cela déclenchera une exception InvalidCastException.

+0

Merci - J'ai essayé ça, ça lance: Impossible de convertir le type 'Entities.BusinessObject ' en 'T' – Ripside

+0

C'est une erreur _compile-time_; ce n'est pas jeté. Ajoutez ', class' à la contrainte générique. – SLaks

+0

Bien sûr. Cela n'a pas aidé cependant. 'public abstract class BusinessObject où T: class, new()'. Pour clarifier et supprimer mon aide externe de l'équation, je vais l'utiliser pour tester (même erreur): 'T myEntity = (T) this;' – Ripside

Questions connexes