C# 通过 SystemReflection 从实体集中的结果中获取属性
C# get properties from result in entitysets wit SystemReflection
所以我想编写一段代码,从 EntitySet 中获取结果,然后利用 SystemReflection 将数据放入另一个对象中。
例子
对象 Ticket
有一个名为 Application
的 属性,此 属性 的值已在名为 [=14= 的关系 table 中定义].该程序必须检查 TicketRelation
中的 Application
属性,如果存在,它将把数据传递到 Ticket
的 Application
属性 中.
这是我目前拥有的:
private object ConvertRelations(object origin, object to)
{
// haal relTable op met getValue op relatie property.
// The propertyInfo types are EntitySets
List<PropertyInfo> relationProperties = new List<PropertyInfo>();
PropertyInfo[] cRels = to.GetType().GetProperties();
foreach (var property in origin.GetType().GetProperties())
{
// all the possible endings of relation table names
if (property.Name.EndsWith("Relatie") || property.Name.EndsWith("Rel") || property.Name.EndsWith("Relaties"))
{
relationProperties.Add(property);
}
}
foreach (var relProp in relationProperties)
{
var parent = relProp.GetValue(origin, null);
var parentProps = parent.GetType().GetProperties();
object match;
PropertyInfo[] matchProps = null;
foreach(var parentProp in parentProps)
{
// the property's name of which I assumed to hold the data I want was called Item
if (parentProp.Name == "Item")
{
match = parentProp.GetValue(parent, null);
if(match != null)
{
matchProps = match.GetType().GetProperties();
}
}
}
}
// this will return the result later on.
return null;
}
但不知何故,我尝试在 parentProp 上调用的 GetValue 方法不起作用。我每次都对 GetValue 使用这种方法,但是当我使用 EntitySet
时,它会抛出一个我不明白的异常。
它抛出的堆栈跟踪 parentProp.GetValue(parent, null)
:
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at TicketSystemDb.DTO.Helper.DTOHelper.ConvertRelations(Object origin, Object to) in C:\TicketSystem\TicketSystemDb\DTO\Helper\DTOHelper.cs:line 90
at TicketSystemDb.DTO.Helper.DTOHelper.SimplifyResult(Object from, Object to) in C:\TicketSystem\TicketSystemDb\DTO\Helper\DTOHelper.cs:line 61
at TicketSystemDb.REPO.TicketREPO.GetTickets() in C:\TicketSystem\TicketSystemDb\REPO\TicketREPO.cs:line 35
at TicketSystemDb.UOW.TicketUOW.GetTickets() in C:\TicketSystem\TicketSystemDb\UOW\TicketUOW.cs:line 21
at TicketSystemAPI.Controllers.TicketController.Get() in C:\TicketSystem\TicketSystemAPI\Controllers\TicketController.cs:line 22
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_1.<GetExecutor>b__3(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
经过一个小时的测试,我终于得到了解决方案。我只是简单地重新设计了数据库,以便每张票只有一个关系 table。这使我可以从关系 table 中获取数据。这里的主要问题是我无法从关系 table 中获得结果,因为存在多个关系,而且如果不使用绑定到特定对象的 LINQ,我将无法访问任何结果。这是更简单的解决方案,但我想让它更具动态性和全球性。
所以考虑到这一点,我只需要 link 票证 table 到相应的关系 table 而不是其他方式。这样做之后,我还对我的代码进行了一些更改,如下所示:
private object ConvertRelations(object origin, object to)
{
List<PropertyInfo> relationProperties = new List<PropertyInfo>();
PropertyInfo[] cRels = to.GetType().GetProperties();
foreach (var property in origin.GetType().GetProperties())
{
if (property.Name.EndsWith("Relatie") || property.Name.EndsWith("Rel") || property.Name.EndsWith("Relaties"))
{
// initial check for class to filter out the auto-generated integer properties
if(property.PropertyType.IsClass)
relationProperties.Add(property);
}
}
// to prevent unnecessary work
if(relationProperties.Count == 0)
{
return null;
}
foreach (var relProp in relationProperties)
{
var parent = relProp.GetValue(origin, null);
var parentProps = parent.GetType().GetProperties();
object match;
// removed matchProps because the were not needed anymore
// loop through cRels because of the database redesign
foreach(var rel in cRels)
{
// This code has been changed because the relation property wasn't an EntitySet anymore.
if (rel.PropertyType.IsClass)
{
// get the link through LINQ instead
var link = parentProps.SingleOrDefault(pr => pr.Name == rel.Name);
if (link != null)
{
// this speaks mostly for itself
// the simplifyresult is used to convert the match to the DTO model to match the property, which is a DTO
match = link.GetValue(parent, null);
rel.SetValue(to, SimplifyResult(match, Assembly.GetExecutingAssembly().CreateInstance("TicketSystemDb.DTO."+rel.PropertyType.Name)), null);
}
}
}
}
return to;
}
所以我想编写一段代码,从 EntitySet 中获取结果,然后利用 SystemReflection 将数据放入另一个对象中。
例子
对象 Ticket
有一个名为 Application
的 属性,此 属性 的值已在名为 [=14= 的关系 table 中定义].该程序必须检查 TicketRelation
中的 Application
属性,如果存在,它将把数据传递到 Ticket
的 Application
属性 中.
这是我目前拥有的:
private object ConvertRelations(object origin, object to)
{
// haal relTable op met getValue op relatie property.
// The propertyInfo types are EntitySets
List<PropertyInfo> relationProperties = new List<PropertyInfo>();
PropertyInfo[] cRels = to.GetType().GetProperties();
foreach (var property in origin.GetType().GetProperties())
{
// all the possible endings of relation table names
if (property.Name.EndsWith("Relatie") || property.Name.EndsWith("Rel") || property.Name.EndsWith("Relaties"))
{
relationProperties.Add(property);
}
}
foreach (var relProp in relationProperties)
{
var parent = relProp.GetValue(origin, null);
var parentProps = parent.GetType().GetProperties();
object match;
PropertyInfo[] matchProps = null;
foreach(var parentProp in parentProps)
{
// the property's name of which I assumed to hold the data I want was called Item
if (parentProp.Name == "Item")
{
match = parentProp.GetValue(parent, null);
if(match != null)
{
matchProps = match.GetType().GetProperties();
}
}
}
}
// this will return the result later on.
return null;
}
但不知何故,我尝试在 parentProp 上调用的 GetValue 方法不起作用。我每次都对 GetValue 使用这种方法,但是当我使用 EntitySet
时,它会抛出一个我不明白的异常。
它抛出的堆栈跟踪 parentProp.GetValue(parent, null)
:
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at TicketSystemDb.DTO.Helper.DTOHelper.ConvertRelations(Object origin, Object to) in C:\TicketSystem\TicketSystemDb\DTO\Helper\DTOHelper.cs:line 90
at TicketSystemDb.DTO.Helper.DTOHelper.SimplifyResult(Object from, Object to) in C:\TicketSystem\TicketSystemDb\DTO\Helper\DTOHelper.cs:line 61
at TicketSystemDb.REPO.TicketREPO.GetTickets() in C:\TicketSystem\TicketSystemDb\REPO\TicketREPO.cs:line 35
at TicketSystemDb.UOW.TicketUOW.GetTickets() in C:\TicketSystem\TicketSystemDb\UOW\TicketUOW.cs:line 21
at TicketSystemAPI.Controllers.TicketController.Get() in C:\TicketSystem\TicketSystemAPI\Controllers\TicketController.cs:line 22
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_1.<GetExecutor>b__3(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
经过一个小时的测试,我终于得到了解决方案。我只是简单地重新设计了数据库,以便每张票只有一个关系 table。这使我可以从关系 table 中获取数据。这里的主要问题是我无法从关系 table 中获得结果,因为存在多个关系,而且如果不使用绑定到特定对象的 LINQ,我将无法访问任何结果。这是更简单的解决方案,但我想让它更具动态性和全球性。
所以考虑到这一点,我只需要 link 票证 table 到相应的关系 table 而不是其他方式。这样做之后,我还对我的代码进行了一些更改,如下所示:
private object ConvertRelations(object origin, object to)
{
List<PropertyInfo> relationProperties = new List<PropertyInfo>();
PropertyInfo[] cRels = to.GetType().GetProperties();
foreach (var property in origin.GetType().GetProperties())
{
if (property.Name.EndsWith("Relatie") || property.Name.EndsWith("Rel") || property.Name.EndsWith("Relaties"))
{
// initial check for class to filter out the auto-generated integer properties
if(property.PropertyType.IsClass)
relationProperties.Add(property);
}
}
// to prevent unnecessary work
if(relationProperties.Count == 0)
{
return null;
}
foreach (var relProp in relationProperties)
{
var parent = relProp.GetValue(origin, null);
var parentProps = parent.GetType().GetProperties();
object match;
// removed matchProps because the were not needed anymore
// loop through cRels because of the database redesign
foreach(var rel in cRels)
{
// This code has been changed because the relation property wasn't an EntitySet anymore.
if (rel.PropertyType.IsClass)
{
// get the link through LINQ instead
var link = parentProps.SingleOrDefault(pr => pr.Name == rel.Name);
if (link != null)
{
// this speaks mostly for itself
// the simplifyresult is used to convert the match to the DTO model to match the property, which is a DTO
match = link.GetValue(parent, null);
rel.SetValue(to, SimplifyResult(match, Assembly.GetExecutingAssembly().CreateInstance("TicketSystemDb.DTO."+rel.PropertyType.Name)), null);
}
}
}
}
return to;
}