2009-01-21 19 views
2

J'ai cette méthode Verify_X qui est appelée pendant le databind pour une valeur sélectionnée dans la liste. Le problème est la source de données fortement typée. Je veux utiliser la classe abstraite BaseDataSource ou une interface pour appeler les méthodes supportées: Paramètres [] et Select(), Au lieu d'utiliser l'implémentation la plus spécifique comme vu ci-dessous.Coulée vers une classe ou une interface abstraite lorsque des génériques sont utilisés

Ceci est donc une méthode peut être utilisée pour tous les différents types de sources de données que j'ai au lieu d'avoir une méthode pour chacun. Ils héritent tous de la même manière.

Voici la chaîne d'héritage/mise en œuvre

public class DseDataSource : ProviderDataSource<SCCS.BLL.Dse, DseKey> 

public abstract class ProviderDataSource<Entity, EntityKey> : BaseDataSource<Entity, EntityKey>, ILinkedDataSource, IListDataSource 
    where Entity : SCCS.BLL.IEntityId<EntityKey>, new() 
    where EntityKey : SCCS.BLL.IEntityKey, new() 

public abstract class BaseDataSource<Entity, EntityKey> : DataSourceControl, IListDataSource, IDataSourceEvents 
    where Entity : new() 
    where EntityKey : new() 

Le BaseDataSource a les méthodes et les propriétés dont j'ai besoin. DseDataSource est mis en œuvre de la manière suivante:

public class DseDataSource : ProviderDataSource<SCCS.BLL.Dse, DseKey> 

Je sais qu'il est possible de modifier la DseDataSource de classe, ajoutez une interface pour accéder aux paramètres [] et sélectionnez(), puis programme contre ce qui permet ce que je veux, mais cela nécessite d'éditer les bibliothèques NetTiers et je suis curieux de voir si cela peut être fait, car cela semblait si difficile.

public static string Verify_DSE(string valueToBind, DseDataSource dataSource) 
    { 
     if (ListContainsValue(dataSource.GetEntityList(), valueToBind)) return valueToBind; 
     CustomParameter p = dataSource.Parameters["WhereClause"] as CustomParameter; 
     if (p != null) 
     { 
      p.Value = "IsActive=true OR Id=" + valueToBind; 
      dataSource.Select(); 
      return valueToBind; 
     } 
     return string.Empty; 
    } 

    private static bool ListContainsValue(IEnumerable list, string value) 
    { 
     if (value.Length == 0) return true; 

     foreach (object o in list) 
     { 
      IEntity entity = o as IEntity; 
      if (entity != null) 
      { 
       if (entity.Id.ToString() == value) 
        return true; 
      } 
     } 
     return false; 
    } 

Le résultat final serait un code tel que:

public static string Verify(string valueToBind, object dataSource) 
{ 
//what is the correct way to convert from object 
BaseDataSource baseInstance = dataSource as BaseDataSource; 

if baseInstance != null) 
{ 
    if (ListContainsValue(baseInstance.GetEntityList(), valueToBind)) return valueToBind; 
    CustomParameter p = baseInstance.Parameters["WhereClause"] as CustomParameter; 
    if (p != null) 
    { 
     p.Value = "IsActive=true OR Id=" + valueToBind; 
     baseInstance.Select(); 
     return valueToBind; 
    } 
} 

return string.Empty; 
} 

Répondre

2

Si vous ne parvenez pas à modifier la définition de classe ou à utiliser une sorte de méthode d'extension, vous pouvez utiliser Reflection. Voici un exemple que je travaille à l'aide d'hypothèses au sujet de votre code:

public static string Verify(string valueToBind, object dataSource) 
    { 
     ////what is the correct way to convert from object 
     //BaseDataSource baseInstance = dataSource as BaseDataSource; 
     Type type = dataSource.GetType(); 
     MethodInfo select = type.GetMethod("Select"); 
     PropertyInfo parameters = type.GetProperty("Parameters"); 
     PropertyInfo parameterGetter = null; 
     object parametersInstance = null; 
     if (parameters != null) 
     { 
      parametersInstance = parameters.GetValue(dataSource, null); 
      type = parametersInstance.GetType(); 
      parameterGetter = type.GetProperty("Item"); 
     } 

     //if baseInstance != null) 
     if (select != null && parameters != null && parameterGetter != null) 
     { 
       if (ListContainsValue(baseInstance.GetEntityList(), valueToBind)) return valueToBind; 
       CustomParameter p = parameterGetter.GetValue(parametersInstance, new object[] {"WhereClause" }) as CustomParameter; 

       if (p != null) 
       { 
         p.Value = "IsActive=true OR Id=" + valueToBind; 
         select.Invoke(dataSource, null); 
         return valueToBind; 
       } 
     } 

     return string.Empty; 
    } 
0

Parce que le code n'est pas utilisable « tel quel », il est très difficile de discuter du problème réel ... pouvez-vous simplifier l'exemple à quelque chose qui ne dépend pas des bibliothèques/classes externes?

Puis-je confirmer: DseDataSource est-il généré à partir de NetTiers? Dans ce cas, NetTiers génère-t-il des classes "partielles"? Si oui, vous pouvez ajouter l'implémentation de l'interface dans un second fichier de classe:

namespace YourNamespace { 
    partial class DseDataSource : IYourInterface { 
     // implement interface 
    } 
} 

Cette fonctionnalité ajoute à la classe DseDataSource sans vous obliger à modifier le code généré.

+0

Non, il n'utilise pas une classe partielle mais oui ce serait une bonne façon de créer l'interface. Je pourrais éditer le modèle de NetTiers pour le rendre partiel ou faire l'interface là. Mais je voyais si le casting pouvait être fait avec ce qui est là. – CRice

+0

Il est difficile de répondre à la question de la distribution car il n'est tout simplement pas clair (à partir de l'exemple) ce que vous essayez de lancer, à quoi, où. Pouvez-vous résumer le problème réel du tout? –

+0

Ok merci, s'il vous plaît voir le bas du message que je viens de l'éditer. – CRice

1

Merci John vous vraiment me mettre sur le bon chemin là-bas. J'ai fini avec le code suivant:

public string Verify(string valueToBind, object dataSource) 
    { 
     IListDataSource listDataSource = dataSource as IListDataSource; 
     if (listDataSource != null) 
     { 
      if (ListContainsValue(listDataSource.GetEntityList(), valueToBind)) return valueToBind; 
     } 

     Type type = dataSource.GetType(); 
     MethodInfo select = type.GetMethod("Select", new Type[0]); 
     PropertyInfo parameterCollectionInfo = type.GetProperty("Parameters"); 
     ParameterCollection pc = parameterCollectionInfo.GetValue(dataSource, null) as ParameterCollection; 

     if (pc != null) 
     { 
      CustomParameter p = pc["WhereClause"] as CustomParameter; 
      if (p != null) 
      { 
       p.Value = "IsActive=true OR Id=" + valueToBind; 
       select.Invoke(dataSource, null); 
       return valueToBind; 
      } 
     } 

     return string.Empty; 
    }