使用methodInfo.Invoke调用的方法返回yield return

时间:2016-02-27 22:16:38

标签: c# reflection yield-return

我正在使用第三方软件包到.Net cms,从内部数据表示到POCO的ORM。为了使它工作,我需要从GitHub获取它的源代码进行调试,看看有什么问题。我发现有一个反射MethodInfo.Invoke调用一个使用yield return的方法。此方法的返回应该使用property.SetValue()分配给POCO的属性。并且这个非常调用返回null,被设置为属性,导致映射无效。

我改变了方法的逻辑以构成IEnumerable<>首先,然后按原样返回,没有收益 - 然后一切都开始正常工作。

我的问题是 - 因为这个软件包是由其他人下载和使用的,所以它被认为是有效的,抛开我的源代码更改 - 也许有一些方法来处理返回带有yield的Invoked方法?我知道yield返回一个ienumerator(状态机),它将在一些IEnumerable上用于类似foreach的循环,但它是用于直接IEnumerable生成器方法调用,这是我第一次看到这种方法的反射调用。感谢。

更新:谢谢@GeorgeVovos。插件是https://github.com/AliSheikhTaheri/Archetype-Mapper。导致问题的代码是:

  1. 致电部分:

        public void SetPropertyValue<T>(object fromObject, PropertyInfo property, T model, IUmbracoMapper mapper)
    {
        var fieldsets = GetArchetypeModel(fromObject);
    
        if (fieldsets != null)
        {
            var type = property.PropertyType.GetGenericArguments()[0];
            var method = GetType().GetMethod("GetItems", BindingFlags.NonPublic | BindingFlags.Instance);
            var genericMethod = method.MakeGenericMethod(type);
            var items = genericMethod.Invoke(this, new object[] { fieldsets, mapper });
            property.SetValue(model, items);
        }
    } 
    
  2. 方法:

        private IEnumerable<T> GetItems<T>(IEnumerable<ArchetypeFieldsetModel> fieldsets, IUmbracoMapper mapper)
    {
        foreach (var fieldset in fieldsets)
        {
            // Instantiate the T
            var instance = (T)Activator.CreateInstance(typeof(T));
    
            // make a dictionary of property alias and value
            var dictionary = fieldset.Properties.ToDictionary(property => FirstToUpper(property.Alias), property => property.Value);
    
            // If fieldset name is the same as instance type then lets map it to the instance
            if (instance.GetType().Name.ToLower() == fieldset.Alias.ToLower())
            {
                mapper.Map(dictionary, (object)instance);
            }
            else // if not then lets find a property with the same name as fieldset name
            {
                var property = instance.GetType().GetProperties().FirstOrDefault(x => x.Name.ToLower() == fieldset.Alias.ToLower());
                if (property != null)
                {
                    var propertyClass = Activator.CreateInstance(property.PropertyType);
                    mapper.Map(dictionary, propertyClass);
    
                    var propertyInfo = instance.GetType().GetProperty(property.Name);
                    propertyInfo.SetValue(instance, Convert.ChangeType(propertyClass, propertyInfo.PropertyType));
                }
            }
    
            yield return instance;
        }
    }
    
  3. 我理解你的答案。看起来当我开始使用插件时,我的代码(模型)错误地定义了使用属性修饰的属性,其中插件代码从CMS映射数据。据我所知,原始的插件代码提供了懒惰的数据获取,而我的更改使它变得渴望。但是如果我最初将属性定义为ienumerables我就不会遇到问题。

    非常感谢!

1 个答案:

答案 0 :(得分:1)

如何调用方法(使用反射与否)无关紧要 它按预期工作。

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass m = new MyClass();

            MethodInfo method = m.GetType().GetMethod("MyMethod");
            var result = (IEnumerable<string>)method.Invoke(m, null);
            foreach (var item in result)
                Console.WriteLine("Printing:" + (item ?? "null"));

            Console.ReadLine();
        }
    }

    public class MyClass
    {
        public IEnumerable<string> MyMethod()
        {
            Console.WriteLine("Returning null");
            yield return null;
            Console.WriteLine("Returning 111");
            yield return "111";
            Console.WriteLine("Returning 222");
            yield return "222";
            Console.WriteLine("Returning 333");
            yield return "333";
        }
    }
}

打印:
enter image description here

您能否提供代码示例以确切了解您的问题?