2009-07-06 7 views
3

Lors de l'utilisation de SubSonic 3 avec des modèles ActiveRecord T4, le code généré affiche de nombreux avertissements concernant la conformité CLS, les éléments inutilisés et l'absence d'implémentation de GetHashCode().SubSonic 3 Code généré par ActiveRecord avec avertissements

Pour les éviter, je l'ai fait les modifications suivantes:

// Structs.tt 
[CLSCompliant(false)]         // added 
public class <#=tbl.CleanName#>Table: DatabaseTable 
{ ... 

// ActiveRecord.tt 
[CLSCompliant(false)]         // added 
public partial class <#=tbl.ClassName#>: IActiveRecord 
{ 
    #region Built-in testing 
    #pragma warning disable 0169       // added 
    static IList<<#=tbl.ClassName#>> TestItems; 
    #pragma warning restore 0169       // added 
    ... 

    public override Int32 GetHashCode()     // added 
    { 
     return this.KeyValue().GetHashCode(); 
    } 

    ... 

Y at-il une meilleure façon de se débarrasser des mises en garde? Ou une meilleure implémentation GetHashCode()?

Répondre

2

Actuellement, la seule façon de se débarrasser des avertissements est de mettre à jour vos templates t4 et de soumettre un bug/correctif à Rob. Ou attendez que quelqu'un d'autre le fasse. En ce qui concerne l'implémentation de GetHashCode, je ne pense pas que vous allez trouver un bon moyen de le faire à travers les templates. La génération de code de hachage dépend beaucoup de l'état de votre objet. Et les gens avec beaucoup de lettres après leur nom travaillent dur et dur pour trouver des algorithmes de code de hachage qui sont rapides et renvoient des résultats avec de faibles chances de collision. Faire cela à l'intérieur d'un modèle qui peut générer une classe avec des millions de permutations différentes de l'état qu'il peut contenir est un gros ordre à remplir.

Probablement la meilleure chose que Rob aurait pu faire aurait été de fournir une implémentation par défaut qui appelle une méthode partielle, vérifie le résultat et le retourne s'il est trouvé. Voici un exemple:

public partial class Foo 
{ 
    public override int GetHashCode() 
    { 
     int? result = null; 
     TryGetHashCode(ref result); 
     if (result.HasValue) 
      return result.Value; 
     return new Random().Next(); 
    } 

    partial void TryGetHashCode(ref int? result); 
} 

public partial class Foo 
{ 
    partial void TryGetHashCode(ref int? result) 
    { 
     result = 5; 
    } 
} 

Si vous compilez cela sans la mise en œuvre de TryGetHashCode, le compilateur omet complètement l'appel à TryGetHashCode et vous passer de la déclaration de résultat à la vérification pour voir si elle a une valeur, qui il ne le sera jamais, donc l'implémentation par défaut du code de hachage est retournée.

+0

+ 1 merci pour l'exemple de code, je n'ai jamais essayé auparavant d'utiliser des méthodes partielles de cette façon. – alexandrul

1

Je voulais également une solution rapide pour cela. La version que j'utilise génère GetHashCode pour les tables qui ont une clé primaire à un seul int. Comme nos tables simples utilisent le texte comme clé primaire, cela n'a pas fonctionné immédiatement. Je fis donc le changement suivant au modèle près de la ligne 273 dans ActiveRecord.tt

<#  if(tbl.PK.SysType=="int"){#> 

     public override int GetHashCode() { 
      return this.<#=tbl.PK.CleanName #>; 
     } 
<#  }#> 
<#  else{#> 
     public override int GetHashCode() { 
      throw new NotImplementedException(); 
     } 
<#  }#> 

Cette GetHashCode est générée de façon pour toutes les tables et arrête les mises en garde, mais lèveront une exception si elle est appelée (que nous ne sommes pas).

Nous l'utilisons pour une application de test, pas pour un site Web ou quoi que ce soit de ce genre, et cette approche peut ne pas être valable dans de nombreuses situations.

+0

+1 J'ai une application plus ancienne avec seulement des clés primaires int/bigint, pour lesquelles cette belle solution pourrait très bien fonctionner. – alexandrul

Questions connexes