【问题标题】:How to invoke a method which takes input parameter as another class object using Reflection in C#?(Method gives argument exception)如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)
【发布时间】: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 FirstName{get;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

标签: c# reflection invokemember


【解决方案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,所以我必须为每个类创建一个程序集对象?请注意,我将类名作为字符串获取。(来自另一个文件)
    猜你喜欢
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    相关资源
    最近更新 更多