NH枚举实体枚举值存为字串

本文介绍如何使用NHibernate将枚举类型的值以字符串形式存储到数据库中,并提供了一个具体的例子,包括实体定义、映射文件配置及单元测试。

NH枚举实体枚举值存为字串

前言:枚举值存默认我们知道保存是整形,实际上这是没有什么意义的,如何让其有意义呢?

那么就将其保存为字串吧,下面的步骤用nh3慢慢将其实现

1:实体(程序集为Eg.Core)

public enum AccountTypes

    {

        Consumer,

        Business,

        Corporate,

        NonProfit

    }

 

    public class Account

    {

        public virtual Guid Id { get; set; }

        public virtual AccountTypes AcctType { get; set; }

        public virtual string Number { get; set; }

        public virtual string Name { get; set; }

}

2:映射

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

    assembly="Eg.Core"

    namespace="Eg.Core">

  <class name ="Account">

  <id name="Id">

    <generator class="guid.comb" />

  </id>

  <natural-id>

    <property name="Number" not-null="true"  />

  </natural-id>

  <property name="Name" not-null="true" />  

    <!--关键地方注意type类型-->

  <property name="AcctType" not-null="true"

             type="NHibernate.Type.EnumStringType`1[[Eg.Core.AccountTypes, Eg.Core]], NHibernate"

            />

  </class>

</hibernate-mapping>

3:其他配置略

4:单元测试

[Test]

        public void CreateAccount()

        {

            //save

            NHibernateHelper.BeginTransaction();

            Account ac = new Account()

            {

                AcctType = AccountTypes .Corporate  ,

                Name ="abcName",

                Number ="210403033"

            };

            NHibernateHelper.Session.Save(ac);

            NHibernateHelper.CommitTransaction();

            NHibernateHelper.CloseSession();

       

            //load

            Account acGet=NHibernateHelper.Session.Get<Account>(ac.Id);

            Console.WriteLine("AcctType(int):" + (int)acGet.AcctType + "; AcctType(str)"+acGet .AcctType );

        }

结果显示:

AcctType(int):2; AcctType(str)Corporate

5:源代码下载:

http://download.youkuaiyun.com/source/3024057

 

<think>我们参考了站内引用,特别是引用[1]和[4]中提到需要工具类来实现枚举与字符的转换,引用[2]和[3]介绍了使用Boost库的describe模块的方法。用户明确要求使用模板来实现这一功能。 由于C++本身不提供枚举的反射,我们需要自己实现。这里提供两种方法: 1. 使用宏和模板技术,构建一个通用的枚举-字符转换工具。 2. 使用Boost库(如果项目允许使用第三方库)。 用户要求使用模板,因此我们重点实现第一种方法。我们将创建一个模板类,其中包含两个静态方法:`ToString`(枚举转字符)和`FromString`(字符枚举)。同时,我们需要一个映射关系(从枚举到字符),这个映射关系需要用户通过宏或者手动提供。 考虑到通用性,我们将使用一个结构体来保存枚举和字符的对应关系,然后通过模板特化来为每种枚举类型提供这个映射。 但是,由于每个枚举类型的不同,我们需要为每个枚举类型单独定义一个映射表。为了简化使用,我们可以定义一个宏。 然而,用户要求的是模板,因此我们不使用宏,而是使用模板特化。但是,模板特化需要为每个枚举类型手动特化,这样比较麻烦。另一种方法是使用可变参数模板在编译期生成映射。 这里我们采用一种折中的方案:用户需要提供一个静态的映射数组(每个枚举类型都需要),然后我们通过模板来生成转换函数。 步骤: 1. 定义一个模板结构体`EnumTraits`,它包含一个静态的`map`(用于存储枚举和字符的对应关系),以及一个静态的`initializer_list`用于初始化这个映射。 2. 为每个枚举类型特化`EnumTraits`,提供对应的映射关系。 3. 实现转换函数。 但是,这样用户需要为每个枚举类型写一个特化,比较繁琐。我们可以利用宏来简化特化的过程(虽然用户要求模板,但宏可以辅助生成模板特化代码,这样用户使用起来更方便)。 因此,我们设计如下: 首先,定义一个模板类`EnumStringMapper`,它有两个静态方法: - `static const char* ToString(E e)`: 将枚举转换为字符 - `static E FromString(const char* str)`: 将字符转换为枚举,如果找不到则返回一个默认(或者抛出异常) 然后,我们要求用户为每个枚举类型提供一个特化的`EnumTraits`,其中包含一个`const std::pair<E, const char*>`的静态数组,以及数组的大小(或者使用`std::array`)。 为了避免重复代码,我们使用宏来定义这个特化。 具体实现如下: </think>在C++中实现枚举与字符的相互转换,可通过模板技术结合静态映射表实现。以下是一个通用模板实现方案: ```cpp #include <string> #include <unordered_map> #include <stdexcept> // 枚举转字符模板 template <typename T> struct EnumStringConverter { static const std::unordered_map<T, std::string> enumToStringMap; static const std::unordered_map<std::string, T> stringToEnumMap; static std::string ToString(T value) { auto it = enumToStringMap.find(value); if (it == enumToStringMap.end()) { throw std::runtime_error("Invalid enum value"); } return it->second; } static T FromString(const std::string& str) { auto it = stringToEnumMap.find(str); if (it == stringToEnumMap.end()) { throw std::runtime_error("Invalid enum string"); } return it->second; } }; // 使用示例:定义颜色枚举 enum class Color { Red, Green, Blue }; // 特化模板映射表 template <> const std::unordered_map<Color, std::string> EnumStringConverter<Color>::enumToStringMap = { {Color::Red, "RED"}, {Color::Green, "GREEN"}, {Color::Blue, "BLUE"} }; template <> const std::unordered_map<std::string, Color> EnumStringConverter<Color>::stringToEnumMap = { {"RED", Color::Red}, {"GREEN", Color::Green}, {"BLUE", Color::Blue} }; // 使用示例: int main() { // 枚举转字符 std::string redStr = EnumStringConverter<Color>::ToString(Color::Red); // "RED" // 字符枚举 Color blue = EnumStringConverter<Color>::FromString("BLUE"); // Color::Blue } ``` ### 关键实现说明 1. **双映射表机制**: - `enumToStringMap`:静态哈希表存储枚举到字符的映射 - `stringToEnumMap`:静态哈希表存储字符枚举的反向映射 - 哈希表查询复杂度为$O(1)$ 2. **模板特化**: - 通过`template<>`为每种枚举类型特化映射表 - 确保类型安全,避免不同枚举间的冲突 3. **异常处理**: - 无效转换时抛出`runtime_error` - 支持自定义错误处理逻辑 4. **C++17特性**: - 使用`unordered_map`实现常量查找 - 支持枚举类(enum class)强类型特性 ### 方案优势 1. **类型安全**:利用枚举类避免隐式转换 2. **高性能**:哈希表实现$O(1)$复杂度转换 3. **可扩展**:添加新枚举只需特化映射表 4. **零依赖**:不依赖第三方库(如Boost) 如需更高级功能(如自动生成映射代码),可结合宏简化映射表定义,或使用Boost.Describe库[^2][^3]。对于大型项目,建议将映射表声明与实现分离到不同文件以提升编译速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值