Fluent NHibernate:将属性应用于通过组件映射的属性的所有成员
我正在使用 Fluent NHibernate (1.2),并且正在致力于实现列级加密。我有一个处理加密的自定义类型,以便域模型可以具有本机明文数据类型(简单字符串、整数、日期时间等),并且所有加密/解密工作都在幕后进行。
我想通过属性指定每个域模型中的哪些属性要加密,并使用约定来指定这些属性的自定义类型,以便域模型是很好的 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.
如上所示,我试图将这一切与 AttributePropertyConvention 结合在一起。这对于简单属性非常有效,例如 EmailAddress 将获得 EncryptedColumnType 的自定义类型。
但它不适用于通过组件映射的复杂类型(例如 LegalName)的属性。我想要的是加密 LegalName 的每个属性,因为我用 [Encrypted] 装饰它。换句话说,我希望 UserRecord 数据库表具有三个加密的 姓名字段——给定的、中间的和家庭的。
似乎 AttributePropertyConvention 根本没有应用于 LegalName 或其任何成员属性。也许我需要使用另一种类型的约定来处理这种情况?
我知道我可以用 [Encrypted] 装饰 PersonName 中的各个属性,而不是装饰 UserRecord 中的 [LegalName] 属性。我对此进行了测试,效果很好。如果有必要,我可以退回到这种方法,但我有兴趣尝试让上面的方法概述发挥作用。
I am using Fluent NHibernate (1.2), and am working on implementing column-level encryption. I have a custom type that handles encryption, so that the domain model can have native cleartext datatypes (simple strings, ints, DateTimes, etc.), and all the encryption/decryption work is behind the scenes.
I would like to specify which properties in each domain model to encrypt via an attribute, and use a Convention to specify the custom type for these properties, so that the domain models are nice POCOs with no mention of the custom type:
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.
As shown above, I am trying to tie this all together with an AttributePropertyConvention. This works well for simple properties, e.g. EmailAddress will get a custom type of EncryptedColumnType.
But it is not working for properties which are complex types (e.g. LegalName) that are mapped via Components. What I want is to encrypt every property of LegalName because I decorated it with [Encrypted]. In other words, I want the UserRecord db table to have three encrypted
name fields--given, middle, and family.
It seems that the AttributePropertyConvention is just not getting applied at all to the LegalName or any of its member properties. Perhaps I need to use another type of Convention to handle this case?
I know I can just decorate the individual properties within PersonName with [Encrypted], instead of decorating the [LegalName] property within UserRecord. I tested this and it works fine. I can fall back to this approach if necessary, but am interested in trying to get the approach outline above to work instead.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
后续我没有找到直接实现我所描述的方法。我可以看到基于属性在 C# 中的工作方式来实现这样的事情是困难或不可能的。
相反,我只是将
[Encrypted]
属性添加到PersonName
类的每个属性中,并让结果数据库表中的那些PersonName
列始终被加密。将来,如果我确实需要将PersonName
映射为另一个实体的非加密“组件”,我也许可以使用禁用的属性来装饰非加密类。 > 对其所有映射列/组件进行加密,覆盖该类的属性/组件映射中找到的任何[Encrypted]
属性。Following up, I did not find a way to directly implement what I described. I could see it being difficult or impossible to implement such a thing based on how attributes work in C#.
Instead, I just added the
[Encrypted]
attribute to each property of thePersonName
class, and let thosePersonName
columns in the resulting database table always be encrypted. In the future, if I do need to mapPersonName
as a non-encrypted "component" of another entity, I could perhaps decorate the non-encrypted class with an attribute that disables encryption for all of its mapped columns/components, overriding any[Encrypted]
attributes found in that class's property/component mappings.