将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()实现?
答案 0 :(得分: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的调用,你从结果的声明转到检查它是否有值,它永远不会,因此返回哈希码的默认实现。
答案 1 :(得分: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并停止了警告,但是如果被调用则抛出异常(我们不是)。
我们使用它来用于测试应用程序,而不是网站或类似的东西,这种方法在许多情况下可能无效。