문제

나는 오늘 다음과 같은 문제를 겪었고, 내 문제에 대한 해결책이 있는지 궁금합니다.

내 아이디어는 익명의 클래스를 구축하고 Winform BindingSource의 데이터 소스로 사용하는 것이 었습니다.

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의 "현재"속성에서 ID를 꺼내는 것입니다. 익명 유형으로 다시 캐스팅 할 수 없기 때문입니다.

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

"현재"유형을 찾고 "ID"속성에 액세스 할 방법이 없다고 생각합니다. 누군가가 좋은 해결책을 가지고 있을지도 모릅니다 ...

나는 ID를 얻는 다른 (그리고 더 나은) 방법이 있다는 것을 알고 있습니다 (반사, 익명의 tpyes를 사용하지 않고 Combobox의 값을 읽고 ...). 우아한 방식으로 최신.

도움이 되었습니까?

해결책

메모, 의견에 따라, 나는 당신이 이와 같은 프로그램 주위를 통과해야 할 때 실제 유형을 사용하는 것이 좋습니다. 익명 유형은 실제로 한 번에 단일 방법으로 로컬로만 사용해야하지만 어쨌든 여기에 내 답변이 있습니다.


컴파일러를 당신에게 적합한 유형을 추론하도록 속임으로써 트릭을 사용하여 할 수 있습니다.

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

그러나 우리는 여기서 한계를 추진하고 있습니다. 실제 유형을 사용하면 더 깨끗하고 느껴질 것입니다.

다른 팁

맞춤형 유형에 캐스트하는 대신 동적 유형을 사용해보십시오.

이벤트 핸들러는 다음과 같이 보입니다.

private void cmdOK_Click(object sender, EventArgs e)
{
    dynamic option = bsOptions.Current;
    if (option.Id == 1) { doSomething(); }
      else { doSomethingElse(); }
}

인용합니다 MSDN:

익명 유형은 객체를 제외한 모든 인터페이스 나 유형에 시전 할 수 없습니다.

C# 3.0에서는 불가능합니다. "동적"변수를 사용하여 런타임에서 속성에 액세스 할 수있는 C# 4.0을 기다려야합니다.

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

당신은 이것을 시도 할 수 있습니다 :

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

보다: 메소드에서 익명 유형을 반환 할 수 없습니까? 진짜?

해당 구문으로 직접 익명 유형의 배열을 선언 할 수도 있습니다.

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top