将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。
希望有所帮助!