Вспомогательный метод для вызова универсальных методов с отражением - PullRequest
0 голосов
/ 11 июля 2019

Есть ли у кого-нибудь лучший способ сделать следующее:

typeof(Service).GetMethod("UpdateData")
    .MakeGenericMethod(dataType)
    .Invoke(_myService, new object[]{ editData, metaData });

Я бы хотел сделать что-то вроде:

_myService.UpdateData<dataType>(editData, metaData);

Но средство доступа <> для шаблонов не будет принимать объекты Type. Я ищу помощника, утилиту, средство доступа или что-то, чтобы сделать эти вызовы обобщенного метода с отражением менее громоздким или хотя бы централизованным.

Более конкретный пример

public class UserService : IUserService
{
  async Task<User> UpdateUser<T>(User user, JsonPatchDocument<T> patch){ //do code }
}

Type dtoType = MagicService.getDynamicDtoType();
Type patchType = typeof(JsonPatchDocument<>).MakeGenericType(dtoType);
dynamic patchDoc = _mapper.Map(patch, typeof(JsonPatchDocument<User>), patchType);
User updateUser = await (Task<User>)typeof(UserService).GetMethod("UpdateUser").MakeGenericMethod(dtoType).Invoke(_userService, new object[]{user, patchDoc})

На самом деле это заканчивается двумя проблемами. Во-первых, dynamic patchDoc не подходит для использования в UpdateUser, о котором у меня есть отдельный вопрос в Stackoverflow (но здесь вы можете использовать утку), и беспорядочный вызов этого общего вызова метода с отражением , Я пытаюсь решить оба, но для этого вопроса я хочу убрать вызов. Если у вас есть идеи по другой части, это действительно отдельная тема: Объявление типа в C # с экземпляром типа

1 Ответ

1 голос
/ 11 июля 2019

В этом ответе не используется рефлексия, но может упростить работу с вашим кодом в некоторых обстоятельствах.

У нас может быть такой класс:

public class MyService
{
    public void UpdateData<T>(Something data, Something otherData)
    {
        // do stuff
    }
}

Позже мы обнаружим, что мы должны вызвать его, используя переменную Type вместо общего аргумента, что может означать использование отражения.Иногда проще добавить неуниверсальную перегрузку к исходному классу и вызвать ее из универсального метода:

public class MyService
{
    public void UpdateData(Type dataType, Something data, Something otherData)
    {
        // do stuff
    }

    public void UpdateData<T>(Something data, Something otherData)
    {
        UpdateData(typeof(T), data, otherData);
    }
}

Мы теряем возможность легко налагать ограничения на аргумент Type, как мы могли бы суниверсальный метод.Мы можем добавить проверку, если она нам понадобится.

Это максимально приблизит вас к коду, который вы пытаетесь написать:

_myService.UpdateData(dataType, editData, metaData);

Предполагается, что вы все еще нуждаетесь вуниверсальные методы вообще.Если вы добавите неуниверсальные перегрузки и обнаружите, что вы больше не вызываете общие, вы можете просто удалить их.

Значительным преимуществом по сравнению с рефлексией является то, что вы можете определить, где вызывается ваш код.Метод, который вызывается только с использованием отражения, будет казаться неиспользованным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...