2011-06-16 97 views
2

我試圖實現一個IUserType的狀態和國家代碼,這將允許我訪問雙字母代碼(存儲在數據庫中)以及全部名稱。我按照NHibernate的3.0食譜的例子,但我的問題是,我StreetAddress類目前映射爲我自動映射配置的組件(P 225):將IUserType映射到流利NHibernate的組件屬性

public override bool IsComponent(Type type) 
{ 
    return type == typeof(StreetAddress); 
} 

有了這個類標識爲一個組件,我不知道如何使用IUserType作爲組件類的屬性,因爲該類未明確映射。沒有任何地方可以告訴流利的NHibernate使用IUserType規範。

回答

5

@Firo接近是可能的,但原來是一個更容易的解決方案。這裏有兩個步驟。首先,我不得不告訴連貫NHibernate不映射StateCountry類,居住在我的領域層:

public override bool ShouldMap(Type type) 
{ 
    return type.Name != "State" && type.Name != "Country"; 
} 

接下來,我根本就創造了IUserType類的約定。事實證明,這是更容易比@Firo建議:

public class CountryUserTypeConvention : UserTypeConvention<CountryType> 
{ 
} 

public class StateUserTypeConvention : UserTypeConvention<StateType> 
{ 
} 

那些IUserTypes的定義,拉出原題引用的食譜的,但如果你不想讀它:

public class CountryType : GenericWellKnownInstanceType<Country, string> 
{ 
    // The StateType is pretty much the same thing, only it uses "StateCode" instead of "CountryCode" 
    private static readonly SqlType[] sqlTypes = 
     new[] {SqlTypeFactory.GetString(2)}; 

    public CountryType() 
     : base(new Countries(), 
       (entity, id) => entity.CountryCode == id, 
       entity => entity.CountryCode) 
    { 
    } 

    public override SqlType[] SqlTypes 
    { 
     get { return sqlTypes; } 
    } 
} 

和從GenericWellKnownInstanceType導出:

[Serializable] 
public abstract class GenericWellKnownInstanceType<T, TId> : 
    IUserType where T : class 
{ 
    private Func<T, TId, bool> findPredicate; 
    private Func<T, TId> idGetter; 
    private IEnumerable<T> repository; 

    protected GenericWellKnownInstanceType(
     IEnumerable<T> repository, 
     Func<T, TId, bool> findPredicate, 
     Func<T, TId> idGetter) 
    { 
     this.repository = repository; 
     this.findPredicate = findPredicate; 
     this.idGetter = idGetter; 
    } 

    public Type ReturnedType 
    { 
     get { return typeof (T); } 
    } 

    public bool IsMutable 
    { 
     get { return false; } 
    } 

    public new bool Equals(object x, object y) 
    { 
     if (ReferenceEquals(x, y)) 
     { 
      return true; 
     } 
     if (ReferenceEquals(null, x) || 
      ReferenceEquals(null, y)) 
     { 
      return false; 
     } 
     return x.Equals(y); 
    } 

    public int GetHashCode(object x) 
    { 
     return (x == null) ? 0 : x.GetHashCode(); 
    } 

    public object NullSafeGet(IDataReader rs, 
           string[] names, object owner) 
    { 
     int index0 = rs.GetOrdinal(names[0]); 
     if (rs.IsDBNull(index0)) 
     { 
      return null; 
     } 
     var value = (TId) rs.GetValue(index0); 
     return repository.FirstOrDefault(x => 
             findPredicate(x, value)); 
    } 

    public void NullSafeSet(IDbCommand cmd, 
          object value, int index) 
    { 
     if (value == null) 
     { 
      ((IDbDataParameter) cmd.Parameters[index]) 
       .Value = DBNull.Value; 
     } 
     else 
     { 
      ((IDbDataParameter) cmd.Parameters[index]) 
       .Value = idGetter((T) value); 
     } 
    } 

    public object DeepCopy(object value) 
    { 
     return value; 
    } 

    public object Replace(object original, 
          object target, object owner) 
    { 
     return original; 
    } 

    public object Assemble(object cached, object owner) 
    { 
     return cached; 
    } 

    public object Disassemble(object value) 
    { 
     return value; 
    } 

    /// <summary> 
    /// The SQL types for the columns 
    /// mapped by this type. 
    /// </summary> 
    public abstract SqlType[] SqlTypes { get; } 
} 

這些類的儲存庫只是對理論值的ReadOnlyCollection e StateCountry對象。再次,從食譜:

public class States : ReadOnlyCollection<State> 
{ 
    // Truncated in the interest of brevity 
    public static State Arizona = new State("AZ", "Arizona"); 
    public static State Florida = new State("FL", "Florida"); 
    public static State California = new State("CA", "California"); 
    public static State Colorado = new State("CO", "Colorado"); 
    public static State Oklahoma = new State("OK", "Oklahoma"); 
    public static State NewMexico = new State("NM", "New Mexico"); 
    public static State Nevada = new State("NV", "Nevada"); 
    public static State Texas = new State("TX", "Texas"); 
    public static State Utah = new State("UT", "Utah"); 

    public States() : base(new State[] 
           { 
            Arizona, Florida, California, Colorado, 
            Oklahoma, NewMexico, Nevada, Texas, Utah 
           } 
     ) 
    { 
    } 
} 

希望這可以幫助那裏的人。

1

我不能測試,但它應該使用常規

public class ComponentConvention : IComponentConvention, IComponentConventionAcceptance 
{ 
    public void Accept(IAcceptanceCriteria<IComponentInspector> criteria) 
    { 
     criteria.Expect(x => x.Type == typeof(StreetAddress); 
    } 

    public void Apply(IComponentInstance instance) 
    { 
     instance.Properties.First(p => p.Name == "CountrCode").CustomType<MyUserType>(); 
    } 
}