Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用methodInfo调用的方法。Invoke返回_C#_Reflection_Yield Return - Fatal编程技术网

C# 使用methodInfo调用的方法。Invoke返回

C# 使用methodInfo调用的方法。Invoke返回,c#,reflection,yield-return,C#,Reflection,Yield Return,我使用第三方软件包来实现.NETCMS,这是一种从内部数据表示到POCO的ORM。为了让它工作起来,我需要从GitHub获取它的源代码进行调试,看看哪里出了问题。我发现存在反射MethodInfo.Invoke调用一个使用yield-return的方法。此方法的返回应该分配给具有property.SetValue()的POCO属性。这个调用返回null,设置为属性,导致映射结果无效 我稍微改变了这个方法的逻辑,先合成IEnumerable,然后返回它,就像它使用普通的返回一样,不产生任何收益——

我使用第三方软件包来实现.NETCMS,这是一种从内部数据表示到POCO的ORM。为了让它工作起来,我需要从GitHub获取它的源代码进行调试,看看哪里出了问题。我发现存在反射MethodInfo.Invoke调用一个使用yield-return的方法。此方法的返回应该分配给具有property.SetValue()的POCO属性。这个调用返回null,设置为属性,导致映射结果无效

我稍微改变了这个方法的逻辑,先合成IEnumerable,然后返回它,就像它使用普通的返回一样,不产生任何收益——然后一切都开始正常工作

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

更新:谢谢@georgevos。插件是。导致问题的代码是:

  • 呼叫部分:

        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);
        }
    } 
    
    public void SetPropertyValue(object fromObject、PropertyInfo属性、T模型、IUmbracoMapper映射器)
    {
    var fieldset=GetArchetypeModel(fromObject);
    如果(字段集!=null)
    {
    var type=property.PropertyType.GetGenericArguments()[0];
    var method=GetType().GetMethod(“GetItems”,BindingFlags.NonPublic | BindingFlags.Instance);
    var genericMethod=method.MakeGenericMethod(类型);
    var items=genericMethod.Invoke(this,新对象[]{fieldset,mapper});
    属性。设置值(型号、项目);
    }
    } 
    
  • 方法:

        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;
        }
    }
    
    private IEnumerable GetItems(IEnumerable字段集,IUmbracoMapper映射器)
    {
    foreach(字段集中的变量字段集)
    {
    //实例化T
    var instance=(T)Activator.CreateInstance(typeof(T));
    //制作属性别名和值的字典
    var dictionary=fieldset.Properties.ToDictionary(property=>FirstToUpper(property.Alias),property=>property.Value);
    //如果字段集名称与实例类型相同,则允许将其映射到实例
    if(instance.GetType().Name.ToLower()==fieldset.Alias.ToLower())
    {
    Map(字典,(对象)实例);
    }
    else//如果不是,则让我们查找与字段集名称同名的属性
    {
    var property=instance.GetType().GetProperties().FirstOrDefault(x=>x.Name.ToLower()==fieldset.Alias.ToLower());
    if(属性!=null)
    {
    var propertyClass=Activator.CreateInstance(property.PropertyType);
    mapper.Map(字典,propertyClass);
    var propertyInfo=instance.GetType().GetProperty(property.Name);
    SetValue(实例,Convert.ChangeType(propertyClass,propertyInfo.PropertyType));
    }
    }
    收益率实例;
    }
    }
    
  • 我理解你的回答。看起来,当我开始使用插件时,我的代码(模型)错误地定义了属性,该属性由插件代码映射来自CMS的数据的属性修饰。据我所知,最初的插件代码提供了惰性数据获取,而我的更改使它变得急切。但是如果一开始我将属性定义为ienumerables,我就不会遇到这个问题


    非常感谢

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

    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";
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    运用系统反思;
    命名空间控制台应用程序6
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    MyClass m=新的MyClass();
    MethodInfo method=m.GetType().GetMethod(“MyMethod”);
    var result=(IEnumerable)method.Invoke(m,null);
    foreach(结果中的var项目)
    Console.WriteLine(“打印:+(项???“空”);
    Console.ReadLine();
    }
    }
    公共类MyClass
    {
    公共IEnumerable MyMethod()
    {
    Console.WriteLine(“返回null”);
    收益返回空;
    控制台写入线(“返回111”);
    收益率回报率“111”;
    控制台写入线(“返回222”);
    收益率回报率“222”;
    控制台写入线(“返回333”);
    收益率回报率“333”;
    }
    }
    }
    
    这将打印:


    您能否提供一个代码示例来准确了解您的问题所在

    你在项目中问过一个问题吗?没有。我让它工作并在我的应用程序中使用。我最感兴趣的是了解反射调用应该如何在返回结果的方法上工作。@他们会看到我的答案并提供有关您问题的更多详细信息。github项目是什么?我们如何重现您的问题?