C # получить свойства из результата в наборах сущностей с SystemReflection - PullRequest
0 голосов
/ 02 октября 2018

Итак, я хочу написать кусок кода, который получает результат из EntitySet и помещает данные в другой объект, используя SystemReflection.

Пример

Объект Ticket имеет свойство с именем Application, значение этого свойства определено в таблице отношений с именем TicketRelation.Программа должна проверить свойство Application в TicketRelation и, если оно там, будет передавать данные в свойство Application Ticket.

Это то, что у меня есть до сих пор:

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;
}

Но почему-то метод GetValue, который я пытаюсь вызвать на parentProp, не работает.Я использую этот метод каждый раз для 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)

1 Ответ

0 голосов
/ 02 октября 2018

Я наконец получил решение после часа тестирования.Я просто перепроектировал базу данных так, чтобы в билете была только одна таблица отношений.Это позволило мне получить данные из таблицы отношений.главная проблема заключалась в том, что я не мог получить результат из таблиц отношений, потому что их было несколько, и я не мог получить доступ к каким-либо результатам без использования LINQ, привязанного к определенному объекту.Это более простое решение, но я хотел сделать его более динамичным и глобальным.

Поэтому, имея в виду, мне просто нужно было связать таблицу Ticket с соответствующей таблицей отношений, а не наоборот.После этого я также внес некоторые изменения в свой код, например:

    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;
    }
...