【问题标题】:SubSonic 3 ActiveRecord generated code with warningsSubSonic 3 ActiveRecord 生成带有警告的代码
【发布时间】:2023-04-10 15:47:02
【问题描述】:

在使用带有 ActiveRecord T4 模板的 SubSonic 3 时,生成的代码会显示许多关于 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() 实现?

【问题讨论】:

    标签: activerecord subsonic subsonic3


    【解决方案1】:

    目前,消除警告的唯一方法是更新您的 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 的调用,你会从 result 的声明开始检查它是​​否有值,但它永远不会,所以返回哈希码的默认实现。

    【讨论】:

    • +1 感谢您提供代码示例,我以前从未尝试过以这种方式使用部分方法。
    【解决方案2】:

    我也想要一个快速的解决方案。我使用的版本确实为具有单个 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 并停止警告,但如果调用它会抛出异常(我们没有)。

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

    【讨论】:

    • +1 我有一个只有 int/bigint 主键的旧应用程序,这个不错的解决方案可能工作得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2023-04-04
    相关资源
    最近更新 更多