我今天遇到了以下问题,我想知道我的问题是否有解决方案。
我的想法是构建匿名类并将其用作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;
}
我想有没有办法找出“当前”的类型并访问“Id”属性? 也许有人有一个很好的解决方案......
我知道还有其他(也有更好的)方法来获取Id(反射,从ComboBox读取值,而不是使用匿名tpyes,...)如果有可能获得Type,我只是很好bsOptions.Current以优雅的方式。
答案 0 :(得分:84)
注意 ,根据评论,我只想指出,当你需要在程序中传递时,我也建议使用真实类型这个。匿名类型应该一次只能在一个方法中本地使用(在我看来),但无论如何,这是我的其余部分。
你可以通过欺骗编译器为你推断出正确的类型来使用技巧:
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);
但我们真的在这里推动极限。使用真实的类型,它看起来也会感觉更干净。
答案 1 :(得分:19)
尝试使用动态类型,而不是强制转换为自定义类型。
您的事件处理程序将如下所示:
private void cmdOK_Click(object sender, EventArgs e)
{
dynamic option = bsOptions.Current;
if (option.Id == 1) { doSomething(); }
else { doSomethingElse(); }
}
答案 2 :(得分:8)
引用MSDN:
除了object之外,匿名类型不能转换为任何接口或类型。
答案 3 :(得分:6)
在C#3.0中,这是不可能的。您将不得不等待C#4.0,它允许使用“动态”变量在运行时访问属性。
答案 4 :(得分:2)
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);
答案 5 :(得分:1)
你可以试试这个:
private void cmdOK_Click(object sender, EventArgs e)
{
var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}
答案 6 :(得分:1)
您也可以使用该语法直接声明匿名类型数组:
var data = new [] {
new {Id = 0, Name = "Foo"},
new {Id = 42, Name = "Bar"},
};
答案 7 :(得分:-1)
JSON使它易于处理,可能会对您有所帮助。
string FirstName = "M. Hamza";
string LastName = "Rajput";
int Age = 25;
var payload = new
{
FirstName,
LastName,
Age
};
Console.WriteLine(payload.FirstName);
DynamicFunc(payload);
JSONFunc(JObject.FromObject(payload));
现在我们有两种方法,一种是使用dynamic,另一种是JSON
private void DynamicFunc(dynamic payload)
{
Console.WriteLine(payload.FirstName);
}
private void JSONFunc(JObject payload)
{
Console.WriteLine(payload["FirstName"]);
}
如果您遇到任何问题,请通知我。祝你好运