Как запустить метод расширения через отражение от другого метода расширения? [дубликат]C#

Место общения программистов C#
Ответить
Anonymous
 Как запустить метод расширения через отражение от другого метода расширения? [дубликат]

Сообщение Anonymous »

У меня есть следующий метод расширения:

Код: Выделить всё

public static class ListExtensions
{
public static IList AddRangeByKey(
this IList list, string keyName,
IEnumerable arrayElements) =>
list.AddRange(keyName, arrayElements);

// the other code is omitted for the brevity
}
Я хочу вызвать указанный выше метод расширения через отражение, потому что я не знаю T. Похоже, мы можем просто использовать отражение:

Код: Выделить всё

public static class UrlHelper
{
public static IEnumerable ToKeyValuePairs(
this object obj)
{
List keyValuePairs = new();

IEnumerable
 props = obj.GetType().GetProperties()
.Where(p => p.GetValue(obj, null) != null);
foreach (PropertyInfo p in props)
{
object value = p.GetValue(obj, null);
IEnumerable enumerable = value as IEnumerable;
if (enumerable != null)
{
MethodInfo addRangeDef = typeof(ListExtensions).GetMethods()
.Where(x => x.Name == "AddRangeByKey" && x.IsGenericMethod)
.FirstOrDefault();
Type ienumerable = value.GetType()
.GetInterface("System.Collections.Generic.IEnumerable`1");
if (ienumerable != null)
{
MethodInfo addRange = addRangeDef
.MakeGenericMethod(ienumerable.GetGenericArguments());
addRange.Invoke(null, new object[] { p.Name, value }); // this
// line of code throws an exception 'addRange.Invoke(null, new
// object[] { p.Name, value })' threw an exception of type
// 'System.Reflection.TargetParameterCountException'.
// Message says `Parameter count mismatch`.

// I tried already like this:
// adRangeDef.Invoke(null, new object[] {
// typeof(UrlHelper), p.Name, value });
}
}
}

return keyValuePairs;
}
}
Код, который я пытаюсь запустить, выглядит следующим образом:

Код: Выделить всё

object queryObject = new SearchUsers
{
Page = 1, PageSize = 10,
Filters = new List{new FilterParameter {
Field = "name",
Val = "Bob" } }
};

IEnumerable foo = queryObject.ToKeyValuePairs();
Итак, эта строка кода addRange.Invoke(null, new object[] { p.Name, value }) выдает исключение:

Код: Выделить всё

'addRange.Invoke(null, new object[] { p.Name, value })' threw
an exception of type
'System.Reflection.TargetParameterCountException'.
Message says `Parameter count mismatch`.`
Я тоже пробовал звонить так:

Код: Выделить всё

addRangeDef.Invoke(null, new object[] { p.Name, value })
Но исключение было выброшено вот так:

Код: Выделить всё

Late bound operations cannot be performed on types or
methods for which ContainsGenericParameters is true.
ОБНОВЛЕНИЕ:
Это решение моего вопроса.

Код: Выделить всё

public static IEnumerable ToKeyValuePairs(this object obj)
{
List keyValuePairs = new();
IEnumerable
 props = obj.GetType().GetProperties()
.Where(p => p.GetValue(obj, null) != null);

foreach (PropertyInfo p in props)
{
object value = p.GetValue(obj, null);
if (value is IEnumerable enumerable && value is not string)
{
Type ienumerableType = value.GetType()
.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IEnumerable));

if (ienumerableType != null)
{
Type elementType = ienumerableType.GetGenericArguments()[0];
MethodInfo addRangeDefinition = typeof(ListExtensions).GetMethods()
.Where(x => x.Name == "AddRangeByKey" &&
x.IsGenericMethod &&
x.GetParameters().Length == 3)
.FirstOrDefault();

if (addRangeDefinition != null)
{
MethodInfo addRange = addRangeDefinition.MakeGenericMethod(elementType);
addRange.Invoke(null, [keyValuePairs, FirstCharacterToLower(p.Name), value]);
}
}
}
else
{
keyValuePairs.Add(new(FirstCharacterToLower(p.Name), value.ToString()));
}
}

return keyValuePairs;
}
Спасибо всем.


Подробнее здесь: https://stackoverflow.com/questions/797 ... ion-method
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»