簡體   English   中英

在 c# 中使用反射調用具有結構參數的方法

[英]invoking a method with struct parameter using reflection in c#

我像這樣創建了一個 Class 庫項目

namespace ClassLibrary1
{
    public class Class1
    {
        public string Method1(int x, string[] y)
        {
            if (x < 100)
            {
                return y[0];
            }
            else
            {
                return y[1];
            }
        }
    }
}

然后,我創建了一個控制台應用程序項目並使用這樣的反射調用Method1

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<object> list = new List<object>();
            list.Add(5);
            string[] x = new string[2] { "N", "F" };
            list.Add(x);
            object output = null;
            string DllFile = @"C:\Users\lenovo\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
            Assembly assembly = Assembly.LoadFrom(DllFile);
            var types = assembly.GetTypes();
            foreach (var j in types)
            {
                object l = j.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
                output = j.InvokeMember("Method1", BindingFlags.InvokeMethod, null, l, list.ToArray());
            }
            Console.WriteLine(output);
            Console.ReadLine();
        }
    }
}

我成功地做到了。 現在,我正在嘗試調用Method1 ,它使用反射將結構變量作為參數。 實際上,我正在嘗試在下面的代碼中調用Method1

namespace ClassLibrary1
{
    public struct Person
    {
        public int personId;
        public string firstName;
        public string lastName;
    }
    public class Class1
    {
        public string Method1(int x, Person y)
        {
            if (x < 100)
            {
                return y.firstName;
            }
            else
            {
                return y.lastName;
            }
        }
    }
}

我看到了一些樣品並嘗試了它們,但我失敗了。 我每次都得到一個例外

System.MissingMethodException: 'Method 'ClassLibrary1.Class1.Method1' not found.'

有人能幫我嗎? 這個異常有什么問題? 在我的第一次嘗試中,我沒有得到這樣的異常。

編輯:下面的代碼是我嘗試調用Method1 ,它使用反射獲取結構變量作為參數

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

namespace ConsoleApp1
{
    public struct Person
    {
        public int personId;
        public string firstName;
        public string lastName;
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<object> list = new List<object>();
            list.Add(5);
            Person x = new Person();
            x.personId = 1;
            x.firstName = "N";
            x.lastName = "F";
            list.Add(x);
            object output = null;
            string DllFile = @"C:\Users\lenovo\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
            Assembly assembly = Assembly.LoadFrom(DllFile);
            var types = assembly.GetTypes();
            foreach (var j in types)
            {
                object l = j.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
                output = j.InvokeMember("Method1", BindingFlags.InvokeMethod, null, l, list.ToArray());
            }
            Console.WriteLine(output);
            Console.ReadLine();
        }
    }
}

為了

namespace ClassLibrary1
{
    public struct Person
    {
        public int personId;
        public string firstName;
        public string lastName;
    }
    public class Class1
    {
        public string Method1(int x, Person y)
        {
            if (x < 100)
            {
                return y.firstName;
            }
            else
            {
                return y.lastName;
            }
        }
    }
}

答案是

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

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<object> list = new List<object>();
            list.Add(5);
            string DllFile = @"C:\Users\lenovo\source\repos\ClassLibrary1\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
            Assembly assembly = Assembly.LoadFrom(DllFile);
            var types = assembly.GetTypes();
            foreach (var i in types)
            {
                if (i.Name == "Person")
                {
                    var instance = Activator.CreateInstance(i);
                    var y = FillObject(instance);
                    list.Add(y);
                }
            }
            object output = null;
            foreach (var i in types)
            {
                if (i.Name == "Class1")
                {
                    var methods = i.GetMethods();
                    foreach (var j in methods)
                    {
                        if (j.Name == "Method1")
                        {
                            output = j.Invoke(Activator.CreateInstance(i), list.ToArray());
                        }
                    }
                }
            }
            Console.WriteLine(output);
            Console.ReadLine();
        }
        static object FillObject(object o)
        {
            var type = o.GetType();
            if (type.IsValueType)
            {
                var fields = type.GetFields();
                foreach (var i in fields)
                {
                    var fieldType = i.FieldType.Name;
                    if (fieldType == "Int32")
                    {
                        i.SetValue(o, 1);
                    }
                    if (fieldType == "String")
                    {
                        i.SetValue(o, "N");
                    }
                }
            }
            return o;
        }
    }
}

嘗試這個:

class Program
{
    static void Main(string[] args)
    {
        //var asy = Assembly.GetExecutingAssembly();
        var asy = Assembly.LoadFrom(@"C:\Users\...\ClassLibrary1.dll");

        // Get class reference
        var t = asy.GetType("ConsoleApp1.Class1");

        // Get method reference
        var m1 = t.GetMethod("Method1", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);

        // create an instance of Class1
        var ctor = t.GetConstructor(Type.EmptyTypes);
        var obj = ctor.Invoke(null);

        var intParam = 10;
        var personParam = new Person() { firstName = "John", lastName = "Smith", personId = 100 };

        var result = m1.Invoke(obj, new object[] { intParam, personParam }) as string;

        Debug.WriteLine(result);
    }
}

其中 class Method1來自以下 class 定義

public class Class1
{
    public string Method1(int x, Person y)
    {
        if (x < 100)
        {
            return y.firstName;
        }
        else
        {
            return y.lastName;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM