C# 将 ExpandoObject 转换为匿名类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10241776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cast ExpandoObject to anonymous type
提问by Sency
Can I cast ExpandoObject to anonymous type ?
我可以将 ExpandoObject 转换为匿名类型吗?
var anoObj = new { name = "testName", email = "testEmail" };
dynamic expandoObj = new System.Dynamic.ExpandoObject();
// Here I'm populating the expandoObj with same property names/types in anonymoustype(anoObj)
// Now, how to convert this ExpandoObject to anonymoustype ?
var newObj = (typeof(anoObj)expandoObj); // This doesn't work
Added Later
稍后添加
// This is my entity
// 这是我的实体
public class Customer
{
#region Public Properties
[ColumnAttribute(Name = "IdColumn")]
public string Id { get; set; }
[ColumnAttribute(Name = "NameColumn")]
public string Name { get; set; }
[ColumnAttribute(Name = "AddressColumn")]
public string Address { get; set; }
[ColumnAttribute(Name = "EmailColumn")]
public string Email { get; set; }
[ColumnAttribute(Name = "MobileColumn")]
public string Mobile { get; set; }
#endregion
}
// -------------------------------------------------------------------------------------
// ------------------------------------------------ -------------------------------------
public class LookupService<TEntitySource>
{
public LookupService ()
{
}
public LookupShowable<TEntitySource, TSelection> Select<TSelection>(Expression<Func<TEntitySource, TSelection>> expression)
{
var lookupShowable = new LookupShowable<TEntitySource, TSelection>();
return lookupShowable;
}
}
public class LookupShowable<TEntitySource,TSelection>
{
public LookupShowable()
{
}
public LookupExecutable<TEntitySource, TSelection, TShow> Show<TShow>(Expression<Func<TEntitySource, TShow>> expression)
{
var lookupExecutable = new LookupExecutable<TEntitySource,TSelection,TShow>();
return lookupExecutable;
}
}
public class LookupExecutable<TEntitySource, TSelection, TShow>
{
public TSelection Execute()
{
// Here I want to create a new instance of TSelection and populate values from database and return it.
}
}
//--------------------------------------------------------------------------------------
//------------------------------------------------ -------------------------------
// This is How I want to call this from front end...
var lookupService = new LookupService<Customer>();
var lookupSelection = lookupService.Select(C => new { C.Id, C.Name, C.Mobile }).Show(C => new { C.Id, C.Name}).Execute();
string sID = lookupSelection.Id;
string sName = lookupSelection.Name;
string sMobile = lookupSelection.Mobile;
Dont think about this middle part.. Purpose of it is another one...
不要考虑这个中间部分..它的目的是另一个......
My problem is in Execute() method in LookupExecutable class. I dont know how to create a new instance of TSelection type and assign values to it. This TSelection type is always an anonymous type..
我的问题出在 LookupExecutable 类中的 Execute() 方法中。我不知道如何创建 TSelection 类型的新实例并为其分配值。此 TSelection 类型始终是匿名类型。
采纳答案by svick
EDIT:I think this question is a prime example of the XY problem. The correct solution doesn't need to concern itself with ExpandoObjector anonymous types, and it would be most likely wrong if it did.
编辑:我认为这个问题是XY 问题的一个主要例子。正确的解决方案不需要关心ExpandoObject或匿名类型,如果这样做很可能是错误的。
You're looking at it the wrong way. You don't need to create an instance of an anonymous object, you need to invoke the code that is passed to you in an expression (which may or may not be creating an anonymous object).
你看错了。您不需要创建匿名对象的实例,您需要调用在表达式中传递给您的代码(可能会或可能不会创建匿名对象)。
If you can create an instance of TEntitySource, then that's simple: Compile()the Expressionthat you got in Select()and then invoke it for each instance of TEntitySource.
如果你可以创建一个实例TEntitySource,那么很简单:Compile()在Expression你的了Select(),然后调用它的每个实例TEntitySource。
If you can't create TEntitySource, you could still do it by rewriting the Expression(using ExpressionVisitor), so that its input is not TEntitySource, but some type you have. But that would require some work from you.
如果您不能创建TEntitySource,您仍然可以通过重写Expression(使用ExpressionVisitor)来实现,这样它的输入就不是TEntitySource,而是您拥有的某种类型。但这需要你做一些工作。
Original answer:
原答案:
No, that won't work. That's simply not how casting or anonymous types work in C#.
不,那行不通。这不是 C# 中强制转换或匿名类型的工作方式。
You can't cast between any two types and expect it to work. Either the object you're casting needs to be the type you're casting to, or one of the two types needs to specify a matching cast operator.
您不能在任何两种类型之间进行转换并期望它起作用。您要转换的对象需要是您要转换到的类型,或者这两种类型之一需要指定匹配的转换运算符。
The fact that the target type is an anonymous type doesn't change anything (except that you can't even try to cast to an anonymous type directly, because you can't name it; the way you're using typeof()is wrong).
目标类型是匿名类型这一事实不会改变任何东西(除了您甚至不能尝试直接转换为匿名类型,因为您无法命名它;您使用的方式typeof()是错误的)。
The fact that the source type is dynamicchanges things a bit. But only in that the search for the cast operator is done at runtime, not at compile time, and you can even create the cast operator at runtime (see DynamicObject.TryCast()). But that's it, it doesn't add any “magical” cast operators.
源类型的事实dynamic稍微改变了一些事情。但只是因为在运行时搜索强制转换运算符,而不是在编译时完成,您甚至可以在运行时创建强制转换运算符(请参阅 参考资料DynamicObject.TryCast())。但就是这样,它没有添加任何“神奇”的转换运算符。
The only way I can imagine something like this working would be if you used a variant of “cast by example”and reflection:
我可以想象这样工作的唯一方法是,如果您使用“按示例投射”和反射的变体:
public T Convert<T>(ExpandoObject source, T example)
where T : class
{
IDictionary<string, object> dict = source;
var ctor = example.GetType().GetConstructors().Single();
var parameters = ctor.GetParameters();
var parameterValues = parameters.Select(p => dict[p.Name]).ToArray();
return (T)ctor.Invoke(parameterValues);
}
You could then use it something like this:
然后你可以像这样使用它:
var expando = new ExpandoObject();
dynamic dynamicExpando = expando;
dynamicExpando.Foo = "SomeString";
dynamicExpando.Bar = 156;
var result = Convert(expando, new { Foo = "", Bar = 1 });
Note that you can't actually invoke Convert()dynamically (by passing it dynamicExpando), because that would mean it would return dynamictoo.
请注意,您实际上无法Convert()动态调用(通过传递它dynamicExpando),因为这意味着它也会返回dynamic。
回答by David Diez
here you have an object madre from an ExpandoObject
这里你有一个来自 ExpandoObject 的对象 madre
var anoObj = new { name = "testName", email = "testEmail" };
dynamic expandoObj = new System.Dynamic.ExpandoObject();
object newObj = expandoObj;
But beware, dynamic objects are very very expensive in resource matters, and what you are asking for does not seem to have any sense. A good aproach for what you are asking in the comments supposing you have to deal with dynamic objects and you want to do something with them:
但请注意,动态对象在资源问题上非常昂贵,您所要求的似乎没有任何意义。假设您必须处理动态对象并且您想对它们做一些事情,那么对于您在评论中提出的问题,这是一个很好的方法:
dynamic expando = new System.Dynamic.ExpandoObject();
var myObj = new Dictionary<string, object>();
myObj["myProperty"] = expando.myProperty;
Any dynamyc object is easily casted to a typed Dicionary.
任何 dynamyc 对象都可以轻松转换为类型化字典。
Hope that helps!
希望有帮助!
回答by Minas
Use JavaScriptSerializer to convert the ExpandoObject to any Type as follows:
使用 JavaScriptSerializer 将 ExpandoObject 转换为任何类型,如下所示:
.....
dynamic myExpandoObject = new ExpandoObject();
var result = ConvertDynamic<myType>(myExpandoObject);
.....
public T ConvertDynamic<T>(IDictionary<string, object> dictionary)
{
var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var obj = jsSerializer.ConvertToType<T>(dictionary);
return obj;
}
This should do the job.
这应该可以完成工作。

