3

在将 SubSonic 3 与 ActiveRecord T4 模板一起使用时,生成的代码显示了许多关于 CLS 合规性、未使用项目和缺少 GetHashCode() 实现的警告。

为了避免它们,我做了以下修改:

// 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();
    }

    ...

有没有更好的方法来摆脱警告?还是更好的 GetHashCode() 实现?

4

2 回答 2

2

目前,摆脱警告的唯一方法是更新您的 t4 模板并向 Rob 提交错误/修复。或者等到其他人这样做。

至于 GetHashCode 实现,我认为您不会通过模板找到一个好方法。哈希码的生成非常依赖于您的对象包含的状态。名字后面有很多字母的人会长期努力地提出哈希码算法,这些算法速度快,返回的结果冲突几率低。从一个模板中执行此操作,该模板可能会生成一个类,该类可能具有数百万种不同的状态排列,这是一项艰巨的任务。

可能 Rob 可以做的最好的事情是提供一个默认实现,它调用部分方法,检查结果并在找到时返回它。这是一个例子:

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;
    }
}

如果你在没有实现 TryGetHashCode 的情况下编译它,编译器会完全忽略对 TryGetHashCode 的调用,然后你从结果的声明到检查它是否有值,它永远不会,所以哈希码的默认实现是回来。

于 2009-07-12T19:13:09.183 回答
1

我也想要一个快速的解决方案。我使用的版本确实为具有单个 int 主键的表生成 GetHashCode。

由于我们的简单表格使用文本作为它们的主键,所以这并不是开箱即用的。所以我对 ActiveRecord.tt 中第 273 行附近的模板进行了以下更改

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

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

这样,为所有表生成 GetHashCode 并停止警告,但如果调用(我们不是)会抛出异常。

我们将其用于测试应用程序,而不是网站或类似的东西,这种方法可能不适用于许多情况。

于 2009-08-10T00:19:07.243 回答