将扩展对象强制转换为匿名类型
本文关键字:类型 转换 扩展 对象 | 更新日期: 2023-09-27 18:31:40
我可以将 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<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;
不要考虑这个中间部分。它的目的是另一个...
我的问题是在 LookupExecutable 类中的 Execute() 方法中。我不知道如何创建 TSelection 类型的新实例并为其赋值。此 TSelection 类型始终是匿名类型。.
编辑:我认为这个问题是XY问题的一个主要例子。正确的解决方案不需要关注ExpandoObject
或匿名类型,如果是这样,很可能是错误的。
你看错了。您不需要创建匿名对象的实例,您需要调用在表达式中传递给您的代码(表达式可能会也可能不会创建匿名对象)。
如果可以创建TEntitySource
的实例,那么这很简单:Compile()
您获得Select()
Expression
,然后为每个TEntitySource
实例调用它。
如果你不能创建TEntitySource
,你仍然可以通过重写Expression
(使用ExpressionVisitor
)来实现,这样它的输入就不会TEntitySource
,而是你拥有的某种类型。但这需要你做一些工作。
原答案:
不,那行不通。这根本不是强制转换或匿名类型在 C# 中的工作方式。
您不能在任何两种类型之间进行转换并期望它起作用。要转换的对象必须是要转换到的类型,或者两种类型之一需要指定匹配的转换运算符。
目标类型是匿名类型这一事实不会改变任何东西(除了您甚至不能尝试直接转换为匿名类型,因为您无法命名它;您使用typeof()
的方式是错误的)。
源类型dynamic
的事实稍微改变了一些事情。但只有在运行时而不是编译时搜索强制转换运算符,您甚至可以在运行时创建强制转换运算符(请参阅DynamicObject.TryCast()
)。但仅此而已,它没有添加任何"神奇"的演员。
我能想象这样的事情工作的唯一方法是,如果你使用"通过示例投射"和反射的变体:
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);
}
然后你可以像这样使用它:
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<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;
}
这应该可以完成这项工作。
这里有一个由 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<string, object>();
myObj["myProperty"] = expando.myProperty;
任何 dynamyc 对象都很容易转换为<字符串,对象>类型化的 Dicionary。
希望对您有所帮助!