60

今日は次のような問題がありましたが、解決策はないかと思いました。

私のアイデアは、匿名クラスを作成し、それをWinFormBindingSourceのデータソースとして使用することでした。

public void Init()
{
    var option1 = new
                  {
                      Id = TemplateAction.Update,
                      Option = "Update the Templates",
                      Description = "Bla bla 1."
                  };

    var option2 = new
                  {
                      Id = TemplateAction.Download,
                      Option = "Download the Templates",
                      Description = "Bla bla 2."
                  };

    var list = new[] {option1, option2}.ToList();

    bsOptions.DataSource = list; // my BindingSource

    // cboTemplates is a ComboBox
    cboTemplates.DataSource = bsOptions; 
    cboTemplates.ValueMember = "Id";
    cboTemplates.DisplayMember = "Option";

    lblInfoTemplates.DataBindings.Add("Text", bsOptions, "Description");
}

これまでのところ問題なく動作します。

私が抱えていた問題は、BindingSourceの「Current」プロパティからIdを取得することでした。これは、匿名タイプにIDをキャストして戻すことができないためです。

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = (???)bsOptions.Current;
}

「Current」のタイプを見つけて「Id」プロパティにアクセスする方法はないと思いますか?多分誰かが良い解決策を持っています...

Idを取得する他の(そしてより良い)方法があることを私は知っています(反射、ComboBoxから値を読み取る、匿名のtpyeを使用しない、...)bsOptionsからTypeを取得できるかどうかだけ興味があります。エレガントな方法で現在。

4

7 に答える 7

96

、コメントに従って、このようにプログラムに渡す必要がある場合は、実数型を使用することをお勧めします。匿名型は、実際には一度に 1 つのメソッドでローカルにのみ使用する必要があります (私の意見では) が、とにかく、これが私の答えの残りの部分です。


コンパイラをだまして正しい型を推測させることで、トリックを使用してそれを行うことができます。

using System;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new { Id = 1, Name = "Bob" };
            TestMethod(a);

            Console.Out.WriteLine("Press enter to exit...");
            Console.In.ReadLine();
        }

        private static void TestMethod(Object x)
        {
            // This is a dummy value, just to get 'a' to be of the right type
            var a = new { Id = 0, Name = "" };
            a = Cast(a, x);
            Console.Out.WriteLine(a.Id + ": " + a.Name);
        }

        private static T Cast<T>(T typeHolder, Object x)
        {
            // typeHolder above is just for compiler magic
            // to infer the type to cast x to
            return (T)x;
        }
    }
}

トリックは、アセンブリ内で、同じ匿名型 (同じプロパティ、同じ順序) が同じ型に解決されることです。これにより、上記のトリックが機能します。

private static T CastTo<T>(this Object value, T targetType)
{
    // targetType above is just for compiler magic
    // to infer the type to cast value to
    return (T)value;
}

利用方法:

var value = x.CastTo(a);

しかし、私たちはここで限界を押し広げています。本物のタイプを使用すると、見た目も手触りもすっきりします。

于 2009-09-11T08:49:19.773 に答える
19

カスタム型にキャストする代わりに、動的型を使用してみてください。

イベント ハンドラーは次のようになります。

private void cmdOK_Click(object sender, EventArgs e)
{
    dynamic option = bsOptions.Current;
    if (option.Id == 1) { doSomething(); }
      else { doSomethingElse(); }
}
于 2012-05-20T09:35:40.900 に答える
8

MSDNを引用するには:

匿名型は、オブジェクト以外のインターフェイスまたは型にキャストできません。

于 2009-09-11T08:41:35.000 に答える
6

C# 3.0 では、これは不可能です。「動的」変数を使用して実行時にプロパティにアクセスできる C# 4.0 を待つ必要があります。

于 2009-09-11T08:42:52.273 に答える
3
public class MyExtensMethods{

    public static T GetPropertyValue<T>(this Object obj, string property)
    {
        return (T)obj.GetType().GetProperty(property).GetValue(obj, null);
    }
}

class SomeClass
{
    public int ID{get;set;}
    public int FullName{get;set;}
}


// casts obj to type SomeClass
public SomeClass CastToSomeClass(object obj)
{
     return new SomeClass()
     {
         ID = obj.GetPropertyValue<int>("Id"),
         FullName = obj.GetPropertyValue<string>("LastName") + ", " + obj.GetPropertyValue<string>("FirstName")
     };
}

....次にキャストするには、次のようにします。

var a = new { Id = 1, FirstName = "Bob", LastName="Nam" };
SomeClass myNewVar = CastToSomeClass(a);
于 2012-04-03T17:20:45.230 に答える
1

あなたはこれを試すことができます:

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}

参照:メソッドから匿名型を返すことはできませんか? 本当に?

于 2009-09-11T08:55:23.067 に答える
1

その構文を使用して、匿名型の配列を直接宣言することもできます。

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
于 2011-02-04T16:23:58.427 に答える