如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)

Posted

技术标签:

【中文标题】如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)【英文标题】:How to invoke a method which takes input parameter as another class object using Reflection in C#?(Method gives argument exception) 【发布时间】:2014-06-20 06:27:03 【问题描述】:

我以下列方式使用反射: a) 加载程序集 b) 获取所有方法及其各自的参数 c) 调用方法

在调用将输入类型作为原始数据类型(int、double、string 等)的方法时不会遇到问题 我尝试以两种方式调用该方法:

(object)method.Invoke(obj,respar);

其中 respar 是一个输入参数数组

object cu = Activator.CreateInstance(typeof(Customer)) as Customer;
respar.SetValue(cu, i);//i = index

(object)type.InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Instance |  BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Default,null, obj, respar);

在哪里

     object obj = Activator.CreateInstance(type,true);//obj

在第一种情况下,我得到一个参数异常错误,在第二种情况下,我得到 Method not found Exception。

例如,如果我调用 GetCustomer(Customer data) 方法,其中 Customer 是一个类,则会引发上述错误。

让我详细解释一下: 有一类 CustomerModel

    public class CustomerModel
   
        public string FirstNameget;set;
        public string LastName get;set;
   

和客户类

    public class Customer
    
       public CustomerModel GetCustomerDetails(CustomerTable tableobj)
       

         //TODO: Get customer details from tableobj and pass to CustomerModel Obj


       

    

我正在尝试通过反射调用此客户类的所有方法。 还有一个类Test:

    public class Test
    
       public void GetAllMethodsInassembly()
       

          //Load assembly
          //Get all classes
          // Foreach Class=> get all methods
          //Invoke each method => get result and store in XML file
       
    

Customer GetCustomerDetails 中的方法如前所述抛出异常。请提出建议。

【问题讨论】:

请提供有关异常的更多详细信息,最好是整个消息。此客户类型在哪里定义? “客户”类型的对象无法转换为“客户”类型。另一个是:找不到方法'GetCustomer'。客户类在我提到的同一个程序集中定义 您是否在程序集中定义了客户类型?你是如何加载程序集的?您是否正在动态加载您也引用的程序集? 以这种方式加载程序集:codeAssembly assembly = Assembly.LoadFile(); foreach (在 assembly.GetTypes() 中输入类型) if (type.IsClass) MethodInfo method = type.GetMethod(methodName);是 使用反射动态加载程序集 尝试使用 LoadFrom 而不是 LoadFile 【参考方案1】:

您是否尝试过使用 Type.GetMethod 而不是返回具有 Invoke 方法的 MethodInfo? 更多信息在这里:http://msdn.microsoft.com/en-us/library/6hy0h0z1(v=vs.110).aspx 另一种选择是使用dynamic

【讨论】:

【参考方案2】:

看起来您已经直接引用了具有 Customer 类型的程序集,并尝试使用 Assembly.LoadFile 动态加载它。我会尝试做这样的事情来获取程序集并调用其中的方法:

Assembly asm = typeof(Customer).Assembly;
foreach (Type type in asm.GetTypes()) 
 
    if (type.IsClass) 
     
        MethodInfo method = type.GetMethod(methodName);
        // TODO: create obj
        // TODO: create respar
        method.Invoke(obj, respar);
    

如果您坚持动态加载程序集并引用它,则必须了解程序集绑定上下文,否则您将继续遇到同样的问题。

程序集绑定上下文是隔离的内存中程序集缓存。 Load(“默认”)、LoadFromLoadFile 都使用不同的上下文。运行时认为在不同上下文中加载的相同程序集的相同类型是不同的。当一个引用的程序集被加载时,它被绑定在默认的“加载”上下文中。

另一个选项可能是使用Assembly.Load 并提供程序集名称。如果程序集是强名称的,则另一个选项可能是更早Load,然后稍后使用LoadFrom,因为LoadFrom 将在加载之前检查具有相同名称的程序集是否已经加载到Load 上下文中从指定的文件。

【讨论】:

我正在尝试获取该程序集的所有方法,而不仅仅是客户。那么,当我尝试访问其他类时,如何仅将提供 typeof 的程序集加载为 Customer 或任何其他类。 @Pragya typeof(Customer).Assembly.GetTypes().Select(t => t.GetMethods()) 将为您提供包含 Customer 的程序集中的所有方法。如果您正在引用它,则无需尝试动态加载程序集。 谢谢迈克。但是如果我试图:加载程序集 => 然后获取所有类 => foreach(class) => 调用每个方法。 @Pragya 我想告诉你的是你不必加载程序集。它已经加载了。查看我的编辑。 Mike,所以我必须为每个类创建一个程序集对象?请注意,我将类名作为字符串获取。(来自另一个文件)

以上是关于如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)的主要内容,如果未能解决你的问题,请参考以下文章

C#通过反射获取类中的方法和参数个数,反射调用方法带参数

如何在 C# 中使用反射调用具有不同类型参数的方法

java 中 如何将“一个类的方法 ”作为参数传到“另一个类的方法”中

c#如何创建类 调用

尝试在同一类中使用反射来调用方法

(C#)怎样在一个窗口中调用另一个窗口中的dataGridView