【问题标题】:C# Reflection Invoke - Returns Generic Object { Type } - Need TypeC# 反射调用 - 返回通用对象 { 类型 } - 需要类型
【发布时间】:2017-02-02 14:53:40
【问题描述】:

我有一个存储过程调用接口,我用它来处理带有实体的存储过程的结果(使用Translate 方法将我们的存储过程的结果转换为可以在 EF 中正常跟踪和使用的实体)

这是基本代码...

List<object> current = new List<object>();
object item = ((Type)currenttype.Current).GetConstructor(System.Type.EmptyTypes).Invoke(new object[0]);

ObjectContext actualContext = ((IObjectContextAdapter)context).ObjectContext;
string className = "";
EntityContainer container = null;
string setName = "";

className = ((Type)currenttype.Current).ToString();
container = actualContext.MetadataWorkspace.GetEntityContainer(((IObjectContextAdapter)context).ObjectContext.DefaultContainerName, DataSpace.CSpace);
setName = (from meta in container.BaseEntitySets
           where meta.ElementType.FullName == className
           select meta.Name).FirstOrDefault();


var t = typeof(ObjectContext).GetMethod("Translate", new Type[] { typeof(DbDataReader), typeof(string), typeof(MergeOption) }).MakeGenericMethod(item.GetType()).Invoke(actualContext, new object[] { reader, setName, MergeOption.AppendOnly });

问题是我不能用我想要的't'做任何事情,它的类型被列为
object {System.Data.Entity.Core.Objects.ObjectResult&lt;POCOClass&gt;}。我无法调用我通常可以在 ObjectResult 类型上调用的任何常规方法,例如 ToArrayToList

我需要一种方法将其转换为System.Data.Entity.Core.Objects.ObjectResult&lt;POCOClass&gt;。不同之处在于“t”首先被列为类型对象。

我不能使用任何强类型转换,因为类型会根据存储过程而改变。我尝试使用 dynamic 关键字而不是 var for t 并且我也尝试使用 Convert.ChangeType。它永远不会从对象基类型改变。动态 t 返回以下错误:

“System.Data.Entity.Core.Objects.ObjectResult”不包含“ToList”的定义

我以为我知道它确实是一个事实......

为了消除混淆,这里有一个手表屏幕截图。第一行是返回的内容,我希望它像第二行一样(参见类型列)。

编辑:可能越来越近了...我添加了这个:

var listedT = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(item.GetType()).Invoke(null, new object[] { t });
current.AddRange(listedT); // Error here...

listedT 变为 object {System.Collections.Generic.List&lt;ReportCatalog.Models.Catalog_Reports&gt;},我收到错误消息,无法从对象转换为 System.Collections.Generic.IEnumerable

【问题讨论】:

  • 你的意思是说你正在输入System.Data.Entity.Core.Objects.ObjectResult&lt;POCOClass&gt;,但你真的想要输入POCOClass
  • 不,我正在获取对象 {System.Data.Entity.Core.Objects.ObjectResult},我只想要 System.Data.Entity.Core.Objects.ObjectResult。 ..
  • object { ... } 是什么意思?它是一个装箱值吗?如果是这种情况,则意味着ObjectResult&lt;&gt; 是一个值类型。
  • Olivier Jacob-Descombes - 我不确定盒装是什么意思。它是 {System.Data.Entity.Core.Objects.ObjectResult} 类型的通用对象。如果我将它转换为 {System.Data.Entity.Core.Objects.ObjectResult} 那么我可以访问 ToArray/ToList 等...但是,POCOClass 直到运行时才知道,所以我不能明确投它。我觉得我需要能够使用反射来投射结果。
  • 我已经为此工作了很长时间,我已经准备好承认这是不可能的。根据我的阅读,从 .Invoke 返回的值是一个装箱对象,在编译时不知道类型的情况下,您无法将其拆箱。

标签: c# entity-framework reflection invoke


【解决方案1】:

由于ObjectResult&lt;T&gt; 也实现了非泛型IEnumerable 接口,因此将其转换为该类型并枚举它。

var e = (IEnumerable)t;
foreach (object o in e) {
    //TODO: use o
}

【讨论】:

  • 我试过这个。我无法在 e 上运行 ToList()。我得到'IEnumerable'不包含'ToList'的定义......我已经在顶部使用System.Linq......如果我像 (IEnumerable)t 一样投射它 - 它按预期工作,我可以调用 ToList()...
  • 如果您有机会将 currentType.Current 作为参数传递,我建议您使用Generic Methods 方法。在这种情况下,您将能够使用强类型功能,例如 LINQ、ToList 等。否则,请考虑使用 Olivier Jacot-Descombes 建议的方法,并使用 foreach 循环填充对象列表。
猜你喜欢
  • 1970-01-01
  • 2017-01-21
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-03
  • 1970-01-01
相关资源
最近更新 更多