通过将委托作为输入的反射调用方法

时间:2015-08-23 18:09:03

标签: c# reflection

我在一个名称空间中定义了一个Employee Class,而代码片段就是这样的

delegate  bool IsPromotable (Employee employee);
class Program
{
    public static void Main(string[] args)
    {
        List<Employee> empList = new List<Employee>();
        empList.Add(new Employee() { EmployeeId = 1, EmployeeName = "A", Salary = 7500, Experience = 2 });
        empList.Add(new Employee() { EmployeeId = 2, EmployeeName = "B", Salary = 11500, Experience = 6 });
        empList.Add(new Employee() { EmployeeId = 3, EmployeeName = "C", Salary = 14500, Experience = 5 });
        empList.Add(new Employee() { EmployeeId = 4, EmployeeName = "D", Salary = 10500, Experience = 7 });

        IsPromotable isPromotableObj = new IsPromotable(EnableToPromote);

        Employee EmployeeObj = new Employee();
        EmployeeObj.PromoteEmployees(empList, isPromotableObj);
    }

    public static bool EnableToPromote(Employee employee)
    {
        if (employee.Experience >= 5 && employee.Salary >= 10000)
        {
            return true;
        }
        else
            return false;
    }
}

class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int Salary { get; set; }
    public int Experience { get; set; }

    public void PromoteEmployees(List<Employee> employeeList, IsPromotable isPromotableObj)
    {

        foreach (Employee employee in employeeList)
        {
            if (isPromotableObj(employee)) 
            {
                Console.WriteLine(" {0} will be promoted in the next R.P. Cycle ", employee.EmployeeName);
            }
        }
        Console.ReadKey();
    }
}

现在,通过反射从单独的命名空间中的一个单独的类中,我想获得Class Type和与之相关的所有其他类型对象。我还想调用PromoteEmployee()方法。我该怎么做?

Console.WriteLine("***************Loading External assembly*************");
Assembly assembly = Assembly.LoadFrom(@"C:\Users\Chiranjib\Documents\visual studio 2012\Projects\DelegatesSampleApplication\DelegatesSampleApplication\bin\Debug\DelegatesSampleApplication.exe");
Type employeeType = assembly.GetType("DelegatesSampleApplication.Employee"); //Gets the System.Type object for the Employee Class from the just loaded assembly with all it's dependencies

object employeeInstance = Activator.CreateInstance(employeeType);//Create an instance of the Employee Class Type
//sets it's properites
Console.WriteLine("***************Setting External assembly propeties for the second instance*************");
object employeeInstance2 = Activator.CreateInstance(employeeType);
//set's it's properties
Console.WriteLine("***************Creating an array list that will hold these employee instances***************");
List<Object> employeeInstanceList = new List<object>();
employeeInstanceList.Add(employeeInstance);
employeeInstanceList.Add(employeeInstance2);
Console.WriteLine("***************Invoking External assembly methods*************");
var agrsDel = new Object[] {(employeeInstance) => return employeeInstance};

dynamic value = employeeType.InvokeMember("PromoteEmployees", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, employeeInstance, new Object[] {employeeInstanceList,args})});
Console.ReadKey();

但是我得到的错误是agrsDel它不能将lambda表达式转换为对象,其次对象不包含employeeId的定义。我错过了什么?

2 个答案:

答案 0 :(得分:1)

我将您的代码更改为使用Delegate.Create委托。这对你有帮助吗?

        //var agrsDel = new Object[] {(employeeInstance) => return employeeInstance};         

        Delegate validationDelegate;
        try
        {
            Type prog = assembly.GetType("DelegatesSampleApplication.Program");
            Type delegateType = assembly.GetType("DelegatesSampleApplication.IsPromotable");
            // Convert the Arg1 argument to a method
            MethodInfo mi = prog.GetMethod("EnableToPromote",
            BindingFlags.Public | BindingFlags.Static);
            // Create a delegate object that wraps the static method
            validationDelegate = Delegate.CreateDelegate(delegateType, mi);
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Phew... not working" );
            return;
        }

答案 1 :(得分:1)

它现在运行正常所以这里是完整的代码,我只做了2次更改 -

1&GT;员工列表是一个对象列表,因此它生成了一个不匹配错误,因为PromoteEmployee需要一个类型列表 - Employee。 我改变了它,所以它现在是通用的。

2 - ;我上面提到的建议,使用Delegate.CreateDelegate

    Console.WriteLine("***************Loading External assembly*************");
        Assembly assembly = Assembly.LoadFrom(@"CXXXXXX\ClassLibrary1\bin\Debug\ClassLibrary1.dll");
        Type employeeType = assembly.GetType("DelegatesSampleApplication.Employee"); //Gets the System.Type object for the Employee Class from the just loaded assembly with all it's dependencies

        object employeeInstance = Activator.CreateInstance(employeeType);//Create an instance of the Employee Class Type
        Console.WriteLine("***************Loading External assembly properties*************");
        PropertyInfo[] propertyInfoColl =  employeeType.GetProperties();
        foreach(var item in propertyInfoColl)
        {
            Console.WriteLine("Loaded Type Property Name {0} and default value {1}", item.Name, item.GetValue(employeeInstance, null));
        }
        Console.WriteLine("***************Setting External assembly propeties for the first instance*************");
        PropertyInfo employeeId = (PropertyInfo)employeeType.GetProperty("EmployeeId");
        employeeId.SetValue(employeeInstance, 1);
        Console.WriteLine("Employee Id Property value now set to " + employeeId.GetValue(employeeInstance,null));
        PropertyInfo employeeName = (PropertyInfo)employeeType.GetProperty("EmployeeName");
       employeeName.SetValue(employeeInstance, "A");
        Console.WriteLine("Employee Name Property value now set to " + employeeName.GetValue(employeeInstance, null));
        PropertyInfo salary = (PropertyInfo)employeeType.GetProperty("Salary");
        salary.SetValue(employeeInstance, 40000);
        Console.WriteLine("Salary Property value now set to " + salary.GetValue(employeeInstance, null));
        PropertyInfo experience = (PropertyInfo)employeeType.GetProperty("Experience");           
        experience.SetValue(employeeInstance, 3);
        Console.WriteLine("Experience Property value now set to " + experience.GetValue(employeeInstance, null));
        Console.WriteLine("***************Setting External assembly propeties for the second instance*************");
        object employeeInstance2 = Activator.CreateInstance(employeeType);
        PropertyInfo employeeId2 = (PropertyInfo)employeeType.GetProperty("EmployeeId");
        employeeId2.SetValue(employeeInstance2, 2);
        Console.WriteLine("Employee Id Property value now set to " + employeeId2.GetValue(employeeInstance2, null));
        PropertyInfo employeeName2 = (PropertyInfo)employeeType.GetProperty("EmployeeName");
        employeeName2.SetValue(employeeInstance2, "B");
        Console.WriteLine("Employee Name Property value now set to " + employeeName2.GetValue(employeeInstance2, null));
        PropertyInfo salary2 = (PropertyInfo)employeeType.GetProperty("Salary");
        salary2.SetValue(employeeInstance2, 50000);
        Console.WriteLine("Salary Property value now set to " + salary2.GetValue(employeeInstance2, null));
        PropertyInfo experience2 = (PropertyInfo)employeeType.GetProperty("Experience");
        experience2.SetValue(employeeInstance2, 6);
        Console.WriteLine("Experience Property value now set to " + experience2.GetValue(employeeInstance2, null));
        Console.WriteLine("***************Creating an array list that will hold these employee instances***************");

        /// list creation goes here 
        var listType = typeof(List<>);
        var constructedListType = listType.MakeGenericType(employeeType);
        var employeeInstanceListType = Activator.CreateInstance(constructedListType);
        var employeeInstanceListInstance = (IList)Activator.CreateInstance(constructedListType);

        employeeInstanceListInstance.Add(employeeInstance);
        employeeInstanceListInstance.Add(employeeInstance2);
        Console.WriteLine("***************Invoking External assembly methods*************");
        //var agrsDel = new Object[] {(employeeInstance) => return employeeInstance};         

        Delegate validationDelegate;
        try
        {
            Type prog = assembly.GetType("DelegatesSampleApplication.Program");
            Type delegateType = assembly.GetType("DelegatesSampleApplication.IsPromotable");
            // Convert the Arg1 argument to a method
            MethodInfo mi = prog.GetMethod("EnableToPromote",
            BindingFlags.Public | BindingFlags.Static);
            // Create a delegate object that wraps the static method
            validationDelegate = Delegate.CreateDelegate(delegateType, mi);
        }
        catch (ArgumentException)
        {
            Console.WriteLine("Phew... not working" );
            return;
        }



        dynamic value = employeeType.InvokeMember("PromoteEmployees", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, employeeInstance, new Object[] { employeeInstanceListInstance, validationDelegate });