10

1 つのプロパティを持つクラスがあるとします。

Public Class MyClass
   Public Property MyItem() as Object
      ....
   End Property
End Class

プロパティの名前を関数呼び出しに渡す必要があります。(サードパーティのフレームワークなので、なぜこのようにする必要があるのか​​尋ねないでください)。例えば

SomeFunc("MyItem")

しかし、私がやりたいのは、文字列を厳密に型指定されたパラメーターに変更することです。つまり、プロパティ名が変更または変更された場合は、ここにも反映する必要があります。

したがって、このタイプの何か:

Dim objectForStrongTyping as New MyClass()
SomeFunc(objectForStrongTyping.MyItem().Name())

これはうまくいかないと確信しています。この強力な型付けを行う方法はありますか? (C#でもVB.NETでもなんでもいいです)

4

6 に答える 6

21

のクラスを使用したソリューションを次に示しSystem.Linq.Expressionsます。

static MemberInfo GetMemberInfo<TObject, TProperty>(
    Expression<Func<TObject, TProperty>> expression
) {
    var member = expression.Body as MemberExpression;
    if (member != null) {
        return member.Member;
    }

    throw new ArgumentException("expression");
}

これをどこかのクラスに投げるだけです(ExpressionHelper?)。

使用法:

class SomeClass {
    public string SomeProperty { get; set; }
}

MemberInfo member = GetMemberInfo((SomeClass s) => s.SomeProperty);
Console.WriteLine(member.Name); // prints "SomeProperty" on the console
于 2009-12-31T06:18:44.747 に答える
3

このソリューションは C# と VB.NET の両方で機能しますが、ラムダ関数の VB.NET 構文はそれほどクリーンではありません。VB ではこのソリューションの魅力が低下する可能性があります。私の例は C# になります。

C# 3 のラムダ関数と式ツリー機能を使用して、必要な効果を得ることができます。基本的には、SomeFuncHelper というラッパー関数を作成し、次のように呼び出します。

MyClass objForStrongTyping = new MyClass();
SomeFuncHelper(() => objForStrongTyping.MyItem);

SomeFuncHelper は次のように実装されています。

void SomeFuncHelper(Expression<Func<object>> expression)
{
    string propertyName = /* get name by examining expression */;
    SomeFunc(propertyName);
}

ラムダ式() => objForStrongTyping.MyItemは、SomeFuncHelper に渡される Expression オブジェクトに変換されます。SomeFuncHelper は Expression を調べ、プロパティ名を取り出し、SomeFunc を呼び出します。私の簡単なテストでは、次のコードはプロパティ名を取得するために機能します() => someObject.SomeProperty

propertyName = ((MemberExpression) ((UnaryExpression) expression.Body).Operand).Member.Name;

おそらく、式ツリーを読み、コードを操作してより堅牢なものにしたいと思うでしょうが、それが一般的な考え方です。

更新:これは Jason のソリューションに似ていますが、ヘルパー関数呼び出し内のラムダ式を (() => obj.Propertyの代わりに(SomeType obj) => obj.Property) 少し単純にすることができます。もちろん、これは、その型のインスタンスがすでに存在している場合にのみ簡単になります。

于 2009-12-31T06:41:00.507 に答える
1

プロパティが 1 つしかない場合は、これを実行できます。クラスの最初のプロパティでプロパティ情報を取得します。

//C# syntax
typeof(MyClass).GetProperties()[0].Name;

'VB syntax
GetType(MyClass).GetProperties()(0).Name

EDIT式を使用できる場合は、この種のリフレクション (C# コード) にプロジェクションを使用することもできます。

public static class ObjectExtensions {
    public static string GetVariableName<T>(this T obj) {
        System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();

        if(objGetTypeGetProperties.Length == 1)
            return objGetTypeGetProperties[0].Name;
        else
            throw new ArgumentException("object must contain one property");
    }
}

class Program {
    static void Main(string[] args) {
        Console.WriteLine(Console.WriteLine(new { (new MyClass()).MyItem}.GetVariableName()););
    }
}

このソリューションでは、クラスは任意の数のプロパティを持つことができ、他の名前を取得できます。

于 2009-12-31T06:18:23.560 に答える
0

リテラルstringを渡す代わりに、定数を含む静的クラスをいつでも使用できます。string

public static class ObjectForStrongTyping
{
    public const string MyItem = "MyItem";
    public const string MyOtherItem = "MyOtherItem";
    // ...
}

コードは次のようになります。

SomeFunc(ObjectForStrongTyping.MyItem);
于 2009-12-31T06:13:21.143 に答える