Fluent NHibernate:将属性应用于通过组件映射的属性的所有成员

Fluent NHibernate:将属性应用于通过组件映射的属性的所有成员,nhibernate,fluent-nhibernate,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,我正在使用Fluent NHibernate(1.2),并且正在致力于实现列级加密。我有一个处理加密的自定义类型,因此域模型可以有原生的明文数据类型(简单字符串、int、datetime等),所有的加密/解密工作都在幕后进行 我希望通过属性指定每个域模型中要加密的属性,并使用约定指定这些属性的自定义类型,以便域模型是良好的POCO,而不提及自定义类型: public class EncryptedAttribute : Attribute {} public class UserRecord

我正在使用Fluent NHibernate(1.2),并且正在致力于实现列级加密。我有一个处理加密的自定义类型,因此域模型可以有原生的明文数据类型(简单字符串、int、datetime等),所有的加密/解密工作都在幕后进行

我希望通过属性指定每个域模型中要加密的属性,并使用约定指定这些属性的自定义类型,以便域模型是良好的POCO,而不提及自定义类型:

public class EncryptedAttribute : Attribute {}

public class UserRecord {
  public virtual Guid Id { get; set; }
  public virtual string Username { get; set; }
  [Encrypted]
  public virtual string EmailAddress { get; set; }
  [Encrypted]
  public virtual DateTime DateOfBirth { get; set; }
  [Encrypted]
  public virtual PersonName LegalName { get; set; }
  // etc.
}

public class PersonName {
  public virtual string Given { get; set; }
  public virtual string Middle { get; set; }
  public virtual string Family { get; set; }
}

public class EncryptedColumnConvention
  : AttributePropertyConvention<EncryptedAttribute> {
  protected override void Apply(
    EncryptedAttribute attribute, IPropertyInstance instance)
  {
    var dbType = typeof(EncryptedColumnType<>).MakeGenericType(domainType);
    instance.CustomType(dbType);  
  }
}

public class UserRecordMap : ClassMap<UserRecord> {
  public UserRecordMap() {
    Id(o => o.Id);
    Map(o => o.Username);
    Map(o => o.EmailAddress);
    Map(o => o.DateOfBirth);
    Component(o => o.LegalName).ColumnPrefix("LegalName");
    // etc.
  }
}

public class PersonNameMap : ComponentMap<PersonName> // etc.
公共类EncryptedAttribute:属性{}
公共类用户记录{
公共虚拟Guid Id{get;set;}
公共虚拟字符串用户名{get;set;}
[加密]
公共虚拟字符串EmailAddress{get;set;}
[加密]
公共虚拟日期时间出生日期{get;set;}
[加密]
公共虚拟人名LegalName{get;set;}
//等等。
}
公共类人名{
给定的公共虚拟字符串{get;set;}
公共虚拟字符串中间{get;set;}
公共虚拟字符串族{get;set;}
}
公共类EncryptedColumn约定
:AttributePropertyConvention{
受保护的覆盖无效应用(
EncryptedAttribute属性,IPropertyInstance)
{
var dbType=typeof(EncryptedColumnType).MakeGenericType(domainType);
CustomType(dbType);
}
}
公共类UserRecordMap:ClassMap{
公共UserRecordMap(){
Id(o=>o.Id);
映射(o=>o.Username);
Map(o=>o.EmailAddress);
Map(o=>o.DateOfBirth);
组件(o=>o.LegalName).ColumnPrefix(“LegalName”);
//等等。
}
}
公共类PersonNameMap:ComponentMap//etc。
如上所示,我正试图将这一切与AttributePropertyConvention联系起来。这适用于简单属性,例如EmailAddress将获得一个自定义类型EncryptedColumnType

但它不适用于通过组件映射的复杂类型(如LegalName)的属性。我想要的是加密LegalName的每个属性,因为我用[Encrypted]修饰它。换句话说,我希望UserRecord db表有三个加密的 名称字段——给定、中间和族

似乎AttributePropertyConvention根本没有应用于LegalName或其任何成员属性。也许我需要用另一种约定来处理这个案子


我知道我可以用[Encrypted]装饰PersonName中的各个属性,而不是装饰UserRecord中的[LegalName]属性。我测试了这个,效果很好。如果有必要,我可以回到这种方法上来,但我有兴趣尝试让上面的方法大纲起作用。

接下来,我没有找到直接实现我描述的方法。根据C#中属性的工作方式,我可以看出实现这样的东西是困难的或不可能的


相反,我只是将
[Encrypted]
属性添加到
PersonName
类的每个属性中,并始终对结果数据库表中的
PersonName
列进行加密。将来,如果我确实需要将
PersonName
映射为另一个实体的非加密“组件”,我可能会使用一个属性来修饰非加密类,该属性禁用其所有映射列/组件的加密,覆盖任何
[加密]
在该类的属性/组件映射中找到属性。

接下来,我没有找到直接实现我所描述内容的方法。根据C#中属性的工作方式,我可以看出实现这样的东西是困难的或不可能的

相反,我只是将
[Encrypted]
属性添加到
PersonName
类的每个属性中,并始终对结果数据库表中的
PersonName
列进行加密。将来,如果我确实需要将
PersonName
映射为另一个实体的非加密“组件”,我可能会使用一个属性来装饰非加密类,该属性禁用其所有映射列/组件的加密,覆盖该类的属性/组件映射中找到的任何
[encrypted]
属性