从匿名类型中获取价值?

假设我们有以下方法:

public object Test() { return new { A = "Test" }; } 

是否有可能获得存储在A中的值?

 var b = Test(); //Any chance to cast this to the anonymous type? 

请注意,从方法返回匿名类型或Tuple<>是一件坏事

但你问了一个关于如何做的问题,而不是“这是一个好主意”……

通过使用动态或reflection……

 dynamic b = Test(); string str = bA; 

或作弊:

 public static object Test() { return new { A = "Test" }; } public static string GetA(object obj) { // We create an anonymous type of the same type of the one in Test() // just to have its type. var x = new { A = string.Empty }; // We pass it to Cast, that will take its T from the type of x // and that will return obj casted to the type of the anonymous // type x = Cast(x, obj); // Now in x we have obj, but strongly typed. So xA is the value we // want return xA; } public static T Cast(T type, object obj) where T : class { return (T)obj; } string str = GetA(Test()); 

在C#中,所有具有相同类型的相同属性的匿名类型将合并在一起。 所以Test()GetA()new { A }属于同一类型。

Cast是从匿名类型中提取类型的有用技巧。 您传递的是您键入的匿名类型的第一个参数(该参数仅用于“激活”genericsT ),并作为第二个参数传递您想要投射的对象。 类似的技巧可用于创建generics类型的集合,例如

 public static T MakeList(T type) { return new List(); } 

//有机会将其转换为匿名类型吗?

是的,您可以通过示例使用强制转换。

 public static T CastByExample(this object obj, T example) { return (T)obj; } 

请注意,这适用于您在同一个程序集中。 如果匿名类型是相同的程序集,则它们具有相同的类型,并且属性在相同的顺序中具有相同类型的相同名称。

然后:

 object b = Test(); var example = new { A = "example" }; var casted = b.CastByExample(example); Console.WriteLine(casted.A); 

或者,您可以使用dynamic

 dynamic b = Test(); Console.WriteLine(bA); 

或者,使用reflection:

 object b = Test(); var property = b.GetType().GetProperty("A"); var value = property.GetValue(b); Console.WriteLine(value); 

或者,您可以做正确的事情并制作名义(即非匿名)类型

有机会将其转换为匿名类型吗?

虽然你可以这样做,但它非常不可靠。 因为无论何时你将改变你的匿名类型的创建,你的代码将突然在其他地方突破而没有任何痕迹。

您可以在这里阅读Jon Skeet在博客中播放匿名类型的所有垮台。 另外值得一读的还有Marc Gravel的评论。

如上文博客中所讨论的中断更改的示例

 using System; static class GrottyHacks { internal static T Cast(object target, T example) { return (T) target; } } class CheesecakeFactory { static object CreateCheesecake() { return new { Fruit="Strawberry", Topping="Chocolate" }; } static void Main() { object weaklyTyped = CreateCheesecake(); var stronglyTyped = GrottyHacks.Cast(weaklyTyped, new { Fruit="", Topping="" }); Console.WriteLine("Cheesecake: {0} ({1})", stronglyTyped.Fruit, stronglyTyped.Topping); } } 

都好。 现在如果你突然意识到你需要将CreateCheeseCake更改为这样的东西

 static object CreateCheesecake() { return new { Fruit="Strawberry", Topping="Chocolate", Base = "Biscuit" }; } 

那你的这条线会发生什么

 var stronglyTyped = GrottyHacks.Cast(weaklyTyped, new { Fruit="", Topping="" }); 

它将不再起作用。