2012-05-09 2 views
6

マネージC++で文字列としてプロパティ名を取得しませんが、C++は1つが、私はC#でこれを行うためのエントリの多くを見る

のために何もすることができますどのように私は、プロパティのセットを持っていますC#部分とC++部分との間でデータを渡す。 C#側では、答えはhereです。私は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)); 

私の問題は、具体的には、このセクションで、私はコールの正しい構文を取得するように見えることができないということです。私はように見えることはできません

() => tz.DisplayName 

オンラインでC++でこれを行う方法を説明するリソースを見つけてください。だれかが経験やリンクを持っていれば、私は本当に助けに感謝します。

答えて

6

私はこれらすべてのラムダと苦労しました。 (CLinqライブラリや他のものも含めて)数時間、そして...私はちょうど考えました:なぜ純粋に静的な決定を使わないのですか?

私達はちょうど

/// Convert X to "X", the classical preprocessing trick 
#define GetPropName(TheClassName, ThePropertyName) #ThePropertyName 

を宣言し、我々は、画面に印刷された "ID" を取得するために

Console::WriteLine(GetPropName(TimeZone, Id)); 

を行うことができます。

ええと...今興味深い部分です。型の安全性。私は、この解決策についてコメントの嵐が聞こえるのを聞いています(「いいえ、これは良くないです、ThePropertyNameがクラスにあるかどうかをチェックしません」)。

OK。解決策:ダミーのTheClassNameのインスタンスでThePropertyNameを使用するマクロを使用して、無意味なコードを生成してみましょう。

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; 
} 
+2

かなり美しい/ハッキー...あなたはCheckForPropertyExistenceを '1で装飾できませんでしたか? NULL:yourcode'を実行時に作成するオブジェクトが2つ少なくなりました。 – xanatos

+0

@ xanatos:はい、いい考えです。 3年が経過した、私はオブジェクトを作成するための正確な推論を覚えていない。たぶん "解決策が見つかりました!"あなたが提案するように興奮が私の行為を妨げました。 –

2

C#のラムダ式は代理人のための構文的な砂糖であるため、C++/CLIで同じ機能を持つことができるように、ラムダ式に相当するデリゲートを見つける必要があります。

あなたの生活を少し簡単にするために、あなたはCLinqを探ることができが(「ラムダ式」の項を参照)LINQの

のためのC++/CLIのラッパー提供:C++ 11を混同しないでくださいをラムダ式をC#ラムダ式で置き換えます。前者はネイティブコードでのみサポートされています。 C++ 11ラムダを使用することは可能ですが、代理人を代理するために余分な作業をする必要があります(this CodeProject articleは主題を探検します)

+0

何が「同等の委任」はありませんC++/CLIおよび管理ランタイムと互換性があります。

/// 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) 

は、今、私たちは完全なサンプルを与えることができます。しかし、見過ごされているマクロがあります! –

+0

@ViktorLatypov - C++/CLIの代表者[ここ](http://www.drdobbs.com/cpp/184401980)をお読みください。 – Attila

+0

申し訳ございません。私は元の質問で使われている "X => F(X)"の構文でLambdasを意味しました。 System.Delegateは完全に有効ですが、実際に参照されているコードを逆コンパイルする簡単な方法はありません。 –

関連する問題