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++中如何做到这一点的资源,所以如果有人有任何经验或链接,我真的很感激任何帮助.
我已经与所有这些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)