假设我们已经通过Entity Framework 6.0从数据库映射了存储过程。我试图通过返回类型过滤存储过程,然后使用返回类型通过WPF填充网格。
以下是涉及的查询:
AssemblyName assemblyName = new AssemblyName("CT_EntityDataModel");
Assembly asm = Assembly.Load(assemblyName);
var myMethods = new ObservableCollection<MethodInfo>();
// The LINQ below can be offloaded to an ICommand for reflection using the Command pattern. If the Command pattern will be used much, it really should also be a Singleton.
var q = from t in asm.GetTypes()
where t.IsClass && t.Namespace == "CT_EntityDataModel"
&& t.Name.Equals("CRMEntities")
select t.GetMethods();
当我使用反射加载存储过程时,我想要的信息在[MethodInfoInstance] .ReturnType.UnderlyingSystemType中。但是,当我尝试获取有关此UnderlyingSystemType的更多信息时,我得到的信息非常少。这是即时窗口的结果:
j.ReturnType.UnderlyingSystemType
{Name = "ObjectResult`1" FullName = "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
[System.RuntimeType]: {Name = "ObjectResult`1" FullName = "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
base: {Name = "ObjectResult`1" FullName = "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
Assembly: {EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
AssemblyQualifiedName: "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Attributes: Public | BeforeFieldInit
BaseType: {Name = "ObjectResult" FullName = "System.Data.Entity.Core.Objects.ObjectResult"}
ContainsGenericParameters: false
DeclaringMethod: 'j.ReturnType.UnderlyingSystemType.DeclaringMethod' threw an exception of type 'System.InvalidOperationException'
DeclaringType: null
FullName: "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"
GenericParameterAttributes: 'j.ReturnType.UnderlyingSystemType.GenericParameterAttributes' threw an exception of type 'System.InvalidOperationException'
GenericParameterPosition: 'j.ReturnType.UnderlyingSystemType.GenericParameterPosition' threw an exception of type 'System.InvalidOperationException'
GenericTypeArguments: {System.Type[1]}
GUID: {3cea792c-523d-3659-8584-7b6e3ad1678b}
HasElementType: false
IsAbstract: false
IsAnsiClass: true
IsArray: false
IsAutoClass: false
IsAutoLayout: true
IsByRef: false
IsClass: true
IsCOMObject: false
IsConstructedGenericType: true
IsContextful: false
IsEnum: false
IsExplicitLayout: false
IsGenericParameter: false
IsGenericType: true
IsGenericTypeDefinition: false
IsImport: false
IsInterface: false
IsLayoutSequential: false
IsMarshalByRef: false
IsNested: false
IsNestedAssembly: false
IsNestedFamANDAssem: false
IsNestedFamily: false
IsNestedFamORAssem: false
IsNestedPrivate: false
IsNestedPublic: false
IsNotPublic: false
IsPointer: false
IsPrimitive: false
IsPublic: true
IsSealed: false
IsSecurityCritical: true
IsSecuritySafeCritical: false
IsSecurityTransparent: false
IsSerializable: false
IsSpecialName: false
IsUnicodeClass: false
IsValueType: false
IsVisible: true
MemberType: TypeInfo
Module: {EntityFramework.dll}
Namespace: "System.Data.Entity.Core.Objects"
ReflectedType: null
StructLayoutAttribute: {System.Runtime.InteropServices.StructLayoutAttribute}
TypeHandle: {System.RuntimeTypeHandle}
TypeInitializer: null
UnderlyingSystemType: {Name = "ObjectResult`1" FullName = "System.Data.Entity.Core.Objects.ObjectResult`1[[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
UnderlyingSystemType或其他地方是否有方法可以让我获得返回类型?
是的,我知道反思的表现太可怕了。一旦我弄清楚如何做到这一点,我将优化IL级别的代码。如果你告诉我使用ADO.NET或其他东西,我会告诉你,你不知道你在说什么。为了您的信息,我能够直接从数据库获取返回类型的唯一简洁方法是sys.dm_exec_describe_first_result_set_for_object,它不包含在SQL Server 2012之前的数据库中;此外,dm_exec_describe_first_result_set_for_object不会从包含动态SQL的过程中提供太多有用的信息。
在最坏的情况下,我想我可以简单地使用正则表达式从MethodInfo实例中获取类型.ReturnType.UnderlyingSystemType.FullName,如下所示:
“System.Data.Entity.Core.Objects.ObjectResult`1 [[CT_EntityDataModel.PROC_RE_ReadImportInvest_Result, CT_EntityDataModel,Version = 1.0.0.0,Culture = neutral, 公钥=空]]“
如果我查看类型PROC_CT_ReadImportInvest_Result,它的定义如下:
namespace CT_EntityDataModel
{
using System;
public partial class PROC_RE_ReadImportInvest_Result
{
public System.DateTime dtDate1 { get; set; }
public string txtData1 { get; set; }
}
}
我想要上述FullName值的“PROC_RE_ReadImportInvest_Result”部分。是否有一种不那么丑陋的方式来获取此类型而不是使用正则表达式来提取它?
谢谢, 德文
[更新(2014年4月20日太平洋标准时间下午5:56):以下是解决此问题的最终代码]:
// If these values will be consumed by a ViewModel, then we need to use an ObservableDictionary here.
public Dictionary<MethodInfo, Type> GetTypesDictionary()
{
// This is for our ViewModel.
AssemblyName assemblyName = new AssemblyName("CT_EntityDataModel");
Assembly asm = Assembly.Load(assemblyName);
// The LINQ below can be offloaded to an ICommand for reflection.
var q = from t in asm.GetTypes()
where t.IsClass && t.Namespace == "CT_EntityDataModel"
&& t.Name.Equals("CRMEntities")
select t.GetMethods();
// We need to filter these to only those that return a dataset.
// q can be offloaded to an IPredicateStrategy that returns only the results that match the strategy.
return (from i in q
from j in i
where j.Name.StartsWith("PROC_") && j.Name.Contains("Global")
let methodType = j.ReturnType.UnderlyingSystemType
where methodType.IsGenericType
let test = j.ReturnType.UnderlyingSystemType.GetGenericArguments()
where test.Length > 0
select j).ToDictionary(j => j, j => j.ReturnType.UnderlyingSystemType.GetGenericArguments()[0]);
// We can use a Strategy pattern to encapsulate the ".Name.StartsWith" logic.
// This would make an interesting extension method.
}
答案 0 :(得分:1)
您似乎正在获得通用代理对象。你可以尝试这样的事情:
var methodType = [MethodInfoInstance].ReturnType.UnderlyingSystemType;
if(methodType.IsGenericType)
{
methodType = methodType.GetGenericArguments()[0];
}
PS。我正在写这篇文章,如果有一些语法错误,请原谅我。