将ExpandoObject强制转换为匿名类型

我可以将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 

稍后添加

//这是我的实体

 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 { public LookupService () { } public LookupShowable Select(Expression<Func> expression) { var lookupShowable = new LookupShowable(); return lookupShowable; } } public class LookupShowable { public LookupShowable() { } public LookupExecutable Show(Expression<Func> expression) { var lookupExecutable = new LookupExecutable(); return lookupExecutable; } } public class LookupExecutable { 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(); 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; 

不要考虑这个中间部分。它的目的是另一个……

我的问题是在LookupExecutable类中的Execute()方法。 我不知道如何创建TSelection类型的新实例并为其赋值。 此TSelection类型始终是匿名类型。

编辑:我认为这个问题是XY问题的一个主要例子。 正确的解决方案不需要关注ExpandoObject或匿名类型,如果确实如此,那么它很可能是错误的。


你正在以错误的方式看待它。 您不需要创建匿名对象的实例,您需要调用在表达式中传递给您的代码(可能创建或不创建匿名对象)。

如果您可以创建TEntitySource的实例,那么这很简单: Compile()您在Select()获得的Expression ,然后为TEntitySource每个实例调用它。

如果你不能创建TEntitySource ,你仍然可以通过重写Expression (使用ExpressionVisitor )来做到这一点,这样它的输入就不是TEntitySource ,而是你拥有的某种类型。 但这需要你做一些工作。


原始答案:

不,那不行。 这根本不是如何在C#中使用强制类型或匿名类型。

你不能在任何两种类型之间进行转换,并期望它能够工作。 您要转换的对象需要是要转换的类型,或者两种类型中的一个需要指定匹配的转换运算符。

目标类型是匿名类型的事实不会改变任何东西(除了你甚至不能尝试直接转换为匿名类型,因为你不能命名它;你使用typeof()是错误)。

源类型是dynamic这一事实改变了一些事情。 但只是因为搜索转换操作符是在运行时完成的,而不是在编译时完成的,你甚至可以在运行时创建转换操作符(参见DynamicObject.TryCast() )。 但就是这样,它不会添加任何“神奇的”演员。

我可以想象像这样工作的唯一方法就是你使用了“逐个演员”和reflection的变体:

 public T Convert(ExpandoObject source, T example) where T : class { IDictionary 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); } 

然后你可以使用这样的东西:

 var expando = new ExpandoObject(); dynamic dynamicExpando = expando; dynamicExpando.Foo = "SomeString"; dynamicExpando.Bar = 156; var result = Convert(expando, new { Foo = "", Bar = 1 }); 

请注意,您实际上无法动态调用Convert() (通过传递dynamicExpando ),因为这意味着它也会返回dynamic

使用JavaScriptSerializer将ExpandoObject转换为任何类型,如下所示:

 ..... dynamic myExpandoObject = new ExpandoObject(); var result = ConvertDynamic(myExpandoObject); ..... public T ConvertDynamic(IDictionary dictionary) { var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var obj = jsSerializer.ConvertToType(dictionary); return obj; } 

这应该做的工作。

这里你有一个来自ExpandoObject的对象

  var anoObj = new { name = "testName", email = "testEmail" }; dynamic expandoObj = new System.Dynamic.ExpandoObject(); object newObj = expandoObj; 

但请注意,动态对象在资源问题上非常昂贵,而您所要求的似乎没有任何意义。 对于您在评论中提出的要求,您需要处理动态对象并希望对它们执行某些操作,这是一个很好的方法:

 dynamic expando = new System.Dynamic.ExpandoObject(); var myObj = new Dictionary(); myObj["myProperty"] = expando.myProperty; 

任何动态物体都很容易被铸造成一个打字的Dicionary。

希望有所帮助!