2013-05-09 1 views
1

je les classes POCO suivantesobjet moulé à boxed typeof (objet)

public interface IObject 
{ 
    Guid Uid { get; set; } 
} 

public class Boo : IObject 
{ 
    public Guid Uid { get; set; } 
    public String Name { get; set; } 
} 

public class Foo : IObject 
{ 
    public Guid Uid { get; set; } 
    public String Name { get; set; } 
} 

Je suis en train d'écrire une méthode générique pour insérer tout type d'objet dans la base de données où le Hériter du type de IObject. J'utilise la méthode suivante pour que (avec ServiceStackOrmLite dessous):

public interface IDataAccess 
{ 
    IDbConnection GetConnection(); 

    Boolean InsertObject<T>(T newObj, IDbConnection connection) where T : IDataObject, new(); 
} 

Essayer d'insérer chaque objet fonctionne séparément comme suit:

public static Boolean AddFoo(this Foo foo) 
{ 
    // DataProvider is initiated using an implementation of IDataAccess 
    return DataProvider.InsertObject(foo, DataProvider.GetConnection()); 
} 

Question:

Je suis en train de utilisez la méthode suivante comme valide pour les deux mais elle échoue. La syntaxe est fausse mais considérez-la comme un pseudo code. Comment puis-je l'obtenir? obj sera une boîte Foo ou Boo exemple

public static Boolean AddObject(this IObject obj) 
{ 
    Type objectType = obj.GetType(); 
    return DataProvider.InsertObject(obj as objectType, DataProvider.GetConnection()); 
} 
+0

Il n'existe pas de "boîte d'objet"; si c'était un objet, il ne serait pas encadré. Et n'importe quelle classe/struct/interface/delegate/etc lancera 'object' ... ni 'Foo' ni' Boo' ne seront *** *** en boîte. Pouvez-vous clarifier la question? –

+0

Puisque 'DataProvider.InsertObject' accepte tout' IDataObject', pourquoi s'embêter? Pourquoi ne pas simplement appeler: 'return DataProvider.InsertObject (obj, DataProvider.GetConnection());' –

+0

@MartinMulder vraisemblablement 'InsertObject' utilise le' T' en interne. Ce serait une erreur, OMI, mais nous y voilà. –

Répondre

3

Je fais l'hypothèse que IObject/IDataObject sont la même chose - sinon il est difficile de voyez comment l'appel fonctionnera jamais. Donc, la meilleure chose à faire est de l'appelant fournir le T:

public static bool AddObject<T>(this T obj) where T : IObject, new() 
{ 
    return DataProvider.InsertObject<T>(obj, DataProvider.GetConnection()); 
} 

Cependant, ce n'est pas toujours possible (l'appelant peut seulement savoir sur IObject), auquel cas vous pouvez également obtenir le exécution de s'inquiéter à ce sujet:

public static bool AddObject(this IObject obj) 
{ 
    return DataProvider.InsertObject((dynamic)obj, DataProvider.GetConnection()); 
} 

La seule autre option est la réflexion par MakeGenericMethod/Invoke - salissante et lent. Franchement, je recommanderais une API non générique ici. La réflexion et les génériques ne font pas de bons amis. Cependant, ServiceStack peut ne pas vous offrir ce luxe, auquel cas l'approche dynamic est probablement votre option la plus pratique ici.

0

Vous pouvez essayer avec l'extension AddObject générique

public static bool AddObject<T>(this T obj) where T:IDataObject, new() 
{ 
    return DataProvider.InsertObject(obj,DataProvider.GetConnection()); 
} 
+1

Ne combira pas puisque InsertObject nécessite' new() '. –

+0

@MartinMulder Vous pouvez ajouter une nouvelle contrainte(), voir mise à jour – jure

Questions connexes