假设我们有以下方法:
public object Test()
{
return new { A = "Test" };
}
是否有可能获得存储在 A 中的值?
var b = Test(); //Any chance to cast this to the anonymous type?
答案 0 :(得分:4)
请注意,从方法中返回匿名类型或Tuple<>
是件坏事
但你问了一个关于如何做的问题,而不是“这是一个好主意”......
使用动态或反射......
dynamic b = Test();
string str = b.A;
或作弊:
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 x.A is the value we
// want
return x.A;
}
public static T Cast<T>(T type, object obj) where T : class
{
return (T)obj;
}
string str = GetA(Test());
在C#中,所有具有相同类型的相同属性的匿名类型将合并在一起。因此,new { A }
和Test()
的{{1}}属于同一类型。
GetA()
是从匿名类型中提取类型的有用技巧。您将第一个参数作为键入的匿名类型传递(该参数仅用于“激活”通用Cast<T>
),并将第二个参数作为要投射的对象传递。类似的技巧可用于创建泛型类型的集合,如
T
答案 1 :(得分:3)
//有机会将其转换为匿名类型吗?
是的,您可以通过示例使用强制转换。
public static T CastByExample<T>(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(b.A);
或者,使用反射:
object b = Test();
var property = b.GetType().GetProperty("A");
var value = property.GetValue(b);
Console.WriteLine(value);
或者,您可以做正确的事情并制作名义(即非匿名)类型。
答案 2 :(得分:0)
有机会将其转换为匿名类型吗?
虽然你可以这样做,但它非常不可靠。因为每当你改变匿名类型的创建时,你的代码就会在其他地方突然中断而没有任何痕迹。
您可以阅读Jon Skeet here在博客中播放匿名类型的所有弊端。另外值得一读的还有Marc Gravel的评论。
示例,如上文博客中所讨论的那样打破了变化。
using System;
static class GrottyHacks
{
internal static T Cast<T>(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="" });
它将不再起作用。