转换为匿名类型

发布于 2024-08-04 09:22:56 字数 1282 浏览 5 评论 0原文

我今天遇到了以下问题,我想知道是否有解决方案。

我的想法是构建匿名类并将其用作 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 的“Current”属性中获取 Id,因为我无法将其转换回匿名类型:

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

我想没有办法找出“Current”的类型并访问“ID”属性? 也许有人有一个很好的解决方案...

我知道还有其他(也是更好的)方法来获取 Id (反射,从组合框中读取值,不使用匿名 tpyes,...)我只是好奇它是否是可以以一种优雅的方式从 bsOptions.Current 中获取 Type 。

I had the following problem today, and I was wondering if there is a solution for my problem.

My idea was to build anonymous classes and use it as a datasource for a 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");
}

That works fine so far.

The problem I had is to get Id out of the "Current" property of the BindingSource, because I can't cast it back to the Anonymous Type:

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

I guess there is no way to find out the type of "Current" and access the "Id" Property?
Maybe someone has a good solution...

I know there are other (and also better) ways to get the Id (Reflection, reading the value from the ComboBox, not using anonymous tpyes,...) I'm just courious if it's possible to get the Type out of bsOptions.Current in an elegant way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

仲春光 2024-08-11 09:22:57

引用 MSDN

匿名类型不能转换为除对象之外的任何接口或类型。

To quote MSDN:

An anonymous type cannot be cast to any interface or type except for object.

思念绕指尖 2024-08-11 09:22:57

在 C# 3.0 中,这是不可能的。您必须等待 C# 4.0,它允许在运行时使用“动态”变量访问属性。

In C# 3.0, this is not possible. You'll have to wait for C# 4.0, which allows accessing properties at runtime using "dynamic" variables.

东京女 2024-08-11 09:22:57
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);
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")
     };
}

.... then to cast you will do:

var a = new { Id = 1, FirstName = "Bob", LastName="Nam" };
SomeClass myNewVar = CastToSomeClass(a);
沐歌 2024-08-11 09:22:57

您可以尝试以下操作:

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

请参阅: 无法从以下位置返回匿名类型方法?真的吗?

you can try this:

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

see: Can't return anonymous type from method? Really?

北城挽邺 2024-08-11 09:22:56

注意,根据评论,我只想指出,当您需要像这样在程序中传递它时,我也建议使用真实类型。匿名类型实际上应该一次只在一个方法中本地使用(在我看来),但无论如何,这是我的答案的其余部分。


您可以使用一个技巧来做到这一点,通过欺骗编译器为您推断正确的类型:

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

但我们确实在突破极限。使用真实的类型,它看起来和感觉起来也会更干净。

Note, as per the comment, I'd just like to point out that I too recommend using a real type when you need to pass it around the program like this. Anonymous types should only really be used locally in a single method at a time (in my opinion), but anyway, here's the rest of my answer.


You can do it using a trick, by tricking the compiler into inferring the right type for you:

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

The trick is that inside the assembly, the same anonymous type (same properties, same order) resolves to the same type, which makes the trick above work.

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

usage:

var value = x.CastTo(a);

But we're really pushing the limits here. Use a real type, it'll look and feel cleaner as well.

太阳男子 2024-08-11 09:22:56

尝试使用动态类型,而不是转换为自定义类型。

你的事件处理程序看起来像这样:

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

Instead of casting to your custom type try using dynamic type.

Your event handler would look something like this:

private void cmdOK_Click(object sender, EventArgs e)
{
    dynamic option = bsOptions.Current;
    if (option.Id == 1) { doSomething(); }
      else { doSomethingElse(); }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文