如何根据道具名称动态设置对象的属性?

时间:2019-04-26 05:06:21

标签: c++ visual-studio c++11 reflection visual-studio-2015

我希望我会清楚自己想做什么。

我想根据提供的对象的属性从数据库中获取数据,然后用检索到的数据填充这些属性。 因此,例如,如果用户定义了一个类

<style>
.is-accordion-submenu-parent[aria-expanded="true"] > a::after{
  display: none;
}
</style>

,然后当他调用class Person { public: int Id; string Name; }; 时,它应该返回MyDatabase.Instance.ExecQuery<Person>()对象,其中装有信息。

我所做的是:用户应按以下方式定义类:

Person

已定义的宏确保将属性的名称和类型添加到class Person : public DBEntity { ENTITIY_PROP(Person , int, Id) ENTITIY_PROP(Person , string, Name) }; 。 现在,如何根据对象的名称设置对象的属性(请参见_propsMeta)?

我的初始解决方案
我虽然要添加将属性映射到设置该属性的函数的ExecQuery,但是我无法对具有不同签名的函数进行map引用。有任何想法吗?如果您认为我需要更改设计以实现所需功能,请告诉我。

map

1 个答案:

答案 0 :(得分:0)

以下是使用boost :: hana的解决方案:

#include <iostream>
#include <string>
#include <unordered_map>
#include <boost/lexical_cast.hpp>
#include <boost/hana/define_struct.hpp>
#include <boost/hana/for_each.hpp>

namespace hana = boost::hana;

// for simplicity I assume that a row is an unordered_map
using row_type = std::unordered_map<std::string, std::string>;

// this is how your users will be defining classes
struct Person {
    BOOST_HANA_DEFINE_STRUCT(Person,
    (int, Id),
    (std::string, Name));
};

struct Car {
    BOOST_HANA_DEFINE_STRUCT(Car,
    (std::string, Brand),
    (int, HorsePower));
};


// convenient function to extract the row's mapped value and set it directly to the target
template <class T>
void set_data(T& target, std::string key, const row_type& row)
{
    target = boost::lexical_cast<T>(row.at(key));
}


// this is what your database will be doing
template <class Entity>
Entity extract(const row_type& row)
{
    Entity entity;

    // accessors provides a tuple of pairs, where the first element of each pair is a "compile-time" string from which you can extract the key
    // and the second element is a function which returns a reference to appropriate member
    hana::for_each(hana::accessors<Entity>(), [&entity, &row](auto unit)
    {
        std::string property_name = hana::to<const char*>(hana::first(unit));
        set_data(hana::second(unit)(entity), property_name, row);
    });

    return entity;
}

// and now test it
int main()
{
    auto person = extract<Person>({{"Id", "42"},{"Name", "John"}});
    std::cout << person.Id << " " << person.Name << std::endl;

    auto car = extract<Car>({{"Brand", "BMW"},{"HorsePower", "95"}});
    std::cout << car.Brand << " " << car.HorsePower << std::endl;

}

您应该仔细阅读documentation page中的相关功能。