Fluent NHibernate组件映射-传递给工厂的字符串DB值生成所需的对象类型

Fluent NHibernate组件映射-传递给工厂的字符串DB值生成所需的对象类型,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,表: 型号: CREATE TABLE Instrument ( Id INT IDENTITY , Name VARCHAR(50) , Tenor VARCHAR(10) //... interface-ITenor { 整数长度{get;} 字符串ToString(); } 类别日期期限:ITenor { 公共整数长度 { 获取{return 1;} } 公共重写字符串ToString() { 返回“天”;

表:

型号:

CREATE TABLE Instrument
(   Id              INT IDENTITY
,   Name            VARCHAR(50)
,   Tenor           VARCHAR(10)
//...
interface-ITenor
{
整数长度{get;}
字符串ToString();
}
类别日期期限:ITenor
{
公共整数长度
{
获取{return 1;}
}
公共重写字符串ToString()
{
返回“天”;
}
}
蒙滕或:伊特诺尔
{
公共整数长度
{
获取{return 30;}
}
公共重写字符串ToString()
{
返回“月”;
}
}
泰诺工厂
{
ITenor GetTenor(弦长或弦长)
{
开关(榫串)
{
案件“日期”:
返回新的日期期限();
打破
案例“月份”:
返回新的monttor();
打破
违约:
抛出新的NotImplementedException(string.Format(“Tenor{0}未实现”,tenorString));
}
}
}
类乐器
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共ITenor基调{get;set;}
}
类映射:类映射
{
公共地图()
{
WithTable(“文书”);
Id(x=>x.Id);
Map(x=>x.Name);
Map(x=>x.期限);
}
}
这是对问题领域的极大简化

线条
Map(x=>x.Tenor)
显然不起作用,因为无法将VARCHAR列隐式转换为ITenor类型。是否有一种方法可以映射为自动使用工厂来获取数据库中指定字符串所需的ITenor,并使用ITenor类中的ToString()还原回数据库


如果没有,你会推荐什么样的重构来实现这一点?非常感谢

一种可能的解决方案是保持字符串在数据库中的原样,并将其映射到TenorString属性。然后添加另一个类型化属性,该属性仅在字符串和类型化值之间进行转换:

    interface ITenor
    {
        int Length { get; }
        string ToString();
    }

    class DayTenor : ITenor
    {
        public int Length
        {
            get { return 1; }
        }

        public override string ToString()
        {
            return "DAY";
        }
    }

    class MonthTenor : ITenor
    {
        public int Length
        {
            get { return 30; }
        }

        public override string ToString()
        {
            return "MONTH";
        }
    }

    class TenorFactory
    {
        ITenor GetTenor(string tenorString)
        {
            switch (tenorString)
            {
                case "DAY":
                    return new DayTenor();
                    break;
                case "MONTH":
                    return new MonthTenor();
                    break;
                default:
                    throw new NotImplementedException(string.Format( "Tenor {0} is not implemented", tenorString ));
            }
        }
    }

    class Instrument
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ITenor Tenor { get; set; }
    }

    class InstrumentMap : ClassMap<Instrument>
    {
        public InstrumentMap()
        {
            WithTable( "Instrument" );
            Id( x => x.Id );
            Map( x => x.Name );
            Map( x => x.Tenor );
        }
    }
TenorString已正常映射,但Tenor属性根本未映射:

class Instrument
{
    public string TenorString { get; set; }
    public ITenor Tenor { 
        get { return GetTenor(this.TenorString); } 
        set { TenorString = value.ToString() }; 
    }
}

当然,Tenor get属性可以返回一个缓存值,当TenorString更改时,该值会重置,以避免每次调用工厂调用。

这可能是最简单的方法。您还可以通过实现IUserType来创建自定义类型:非常感谢Aleris和Stuart。我宁愿实现IUserType,因为我不想攻击Instrument类,但这是一个非常简单的解决方法。
Map( x => x.TenorString );