如何在托管c ++中将属性名称作为字符串获取

Fry*_*Fry 6 managed-c++ c++-cli properties visual-c++

我在C#中看到很多用于执行此操作的条目,但对C++没有任何用处

我在一些托管C++代码中有一组属性,用于在C#部分和c ++部分之间传递数据.在C#方面,这里给出的答案非常有效,我想用C++做类似的事情.链接中包含的解决方案的副本:

string NameOf<T>(Expression<Func<T>> expr) {
    return ((MemberExpression) expr.Body).Member.Name;
}

var gmtList = new SelectList(repository.GetSystemTimeZones(),
    NameOf(() => tz.Id),
    NameOf(() => tz.DisplayName));
Run Code Online (Sandbox Code Playgroud)

我的问题是,我似乎无法获得正确的调用语法,具体来说,这部分:

() => tz.DisplayName
Run Code Online (Sandbox Code Playgroud)

我似乎无法在网上找到我在C++中如何做到这一点的资源,所以如果有人有任何经验或链接,我真的很感激任何帮助.

Vik*_*pov 6

我已经与所有这些lambda和酷的System :: Linq名称空间(包括CLinq库和其他东西)挣扎了几个小时然后......我只是想:为什么不使用纯粹的静态决定?

我们只是声明了

/// Convert X to "X", the classical preprocessing trick
#define GetPropName(TheClassName, ThePropertyName) #ThePropertyName
Run Code Online (Sandbox Code Playgroud)

然后我们就可以做到

Console::WriteLine( GetPropName(TimeZone, Id) );
Run Code Online (Sandbox Code Playgroud)

在屏幕上打印"Id".

是的......现在是有趣的部分.类型安全.我听到关于这个解决方案的评论风暴("不!这不好,它不会检查ThePropertyName是否在课堂上!")

好.解决方案:让我们使用宏在一个虚拟的TheClassName实例中使用ThePropertyName来生成一些无意义的代码.

/// This macro will produce the compilation error if ThePropertyName is not in the class named TheClassName
#define CheckForPropertyExistence(TheClassName, ThePropertyName) \
/* Create an array of Objects which will be converted to string and ignored*/ \
(gcnew array<System::Object^> { (gcnew TheClassName())->ThePropertyName })->ToString()

/// We get the property name using the "dinosaur strategy" - good old macro concatenated with the empty string which in turn is formed in CheckFor() macro
#define GetPropertyName(TheClassName, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + CheckForPropertyExistence(TheClassName, ThePropertyName)->Substring(0,0)
Run Code Online (Sandbox Code Playgroud)

现在我们可以给出完整的样本:

using namespace System;

/// Sample class
public ref class TheTimeZone
{
public:
    TheTimeZone()
    {
        _Id = 0;
        _DisplayName = "tmp";
    }

    property int Id
    {
    public:
        int get() {return _Id;}
        void set(int v) { _Id = v; }
    }

    property String^ DisplayName
    {
    public:
        String^ get() { return _DisplayName; }
        void set(String^ v) { _DisplayName = v; }
    }

private:
    int _Id;
    String^ _DisplayName;
};

/// This macro will produce the error if ThePropertyName is not in the class named TheClassName
#define CheckForPropertyExistence(TheClassName, ThePropertyName) \
/* Create an array of Objects which will be converted to string and ignored*/ \
(gcnew array<System::Object^> { (gcnew TheClassName())->ThePropertyName })->ToString()

/// We get the property name using the "dinosaur strategy":
/// good old macro concatenated with the empty string
/// which in turn is formed in CheckFor() macro
#define GetPropertyName(TheClassName, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + \
CheckForPropertyExistence(TheClassName, ThePropertyName)->Substring(0,0)

/// To get properties from objects with no default constructor
#define GetPropertyNameForObject(TheObject, ThePropertyName) \
(gcnew System::String(#ThePropertyName)) + \
(gcnew array<System::Object^> { (TheObject)-> ThePropertyName })->ToString()->Substring(0,0)

/// Test for our macros
int main(array<System::String ^> ^args)
{
    /// Prints "Length"
    /// We cannot use default constructor here
    Console::WriteLine(GetPropertyNameForObject (gcnew System::String("test"), Length) );

    /// Prints "Id"
    Console::WriteLine(GetPropertyName (TheTimeZone, Id) );

/// Uncomment and get the error
    //Console::WriteLine(GetPropertyName (TheTimeZone, Id23) );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 相当漂亮/ hacky ......难道你不能用`1来装饰CheckForPropertyExistence吗?NULL:yourcode`,以便在运行时创建两个较少的对象? (2认同)