使用反射调用扩展方法 [英] Invoke extension method using reflection

查看:74
本文介绍了使用反射调用扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象列表,因为我将有不同种类的类(例如:Class1, Class2),但我不知道列表将包含什么.

然后为每个类创建一个扩展方法
(例如:public static Save(this Class1 c1) {})

当我为列表创建扩展方法后,
(例如:public static Save(this List<object> lstObj) {})

该方案是在用对象填充列表之后,我将其称为列表的扩展Save() 方法.在这种方法中,我需要遍历所有对象,对于foreach对象,我需要为其调用扩展的Save() 方法.

有什么想法吗?

I have a List of object because I will have diferent kind of classes (ex: Class1, Class2) and I don''t know what the list will contains.

Then I have create for each class an extension method
(ex: public static Save(this Class1 c1) {})

As I have created an extension method for the list
(ex: public static Save(this List<object> lstObj) {})

The scenario is after filling the list with the object I call the extended Save() method of the list. In this method I need to loop through all the object and for foreach object I need to call the extented Save() method for it.

Any idea?

推荐答案

我建​​议尝试通过让Class1Class2实现某种类型的ISaveable接口来尝试解决此问题,但是如果那无法完成,那么这里有两种不同的解决方案.

第一个尝试在调用程序集中找到任何匹配的扩展方法,第二个效率更高,但是会强制您指定拥有扩展方法的类型:

I would recommend trying to solve this by having the Class1 and Class2 implement some sort of ISaveable interface instead, but if that can''t be done then here''s two different solutions.

The first one tries to find any matching extension method in the calling assembly, and the second one is slightly more efficient but forces you to specify the type owning the extension methods:

public static class Extensions
{
    public static void Save(this A instance)
    {
        Console.WriteLine("Saving A");
    }
    public static void Save(this B instance)
    {
        Console.WriteLine("Saving B");
    }
    private static bool IsMethodOk(MethodInfo method, object obj)
    {
        return
            method.IsStatic
            &&
            method.GetParameters().Count() == 1
            &&
            method.GetParameters()[0].ParameterType == obj.GetType();
    }
    public static void Save1(this IList<object> list)
    {
        foreach (object obj in list)
        {
            foreach (Type type in Assembly.GetCallingAssembly().GetTypes())
            {
                bool hasSaved = false;
                foreach (MethodInfo method in type.GetMethods())
                {
                    if (IsMethodOk(method, obj))
                    {
                        method.Invoke(null, new[] { obj });
                        hasSaved = true;
                        break;
                    }
                }
                if (hasSaved)
                    break;
            }
        }
    }
    public static void Save2(this IList<object> list, Type extensionClass)
    {
        foreach (object obj in list)
        {
            foreach (MethodInfo method in extensionClass.GetMethods())
            {
                if (IsMethodOk(method, obj))
                {
                    method.Invoke(null, new[] { obj });
                    break;
                }
            }
        }
    }
}



希望这会有所帮助,
Fredrik



Hope this helps,
Fredrik


我已经使用以下代码解决了我的问题...

I have resolved my problem using the below code...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Namespace1;
using System.Reflection;
using System.Data.Linq;

namespace Namespace2
{
    public static class Extensions
    {
        public static void Save(this IList<object> list)
        {
            if (list.Count > 0)
            {
                Assembly thisAssembly = Assembly.GetExecutingAssembly();//Assembly containin the extension method
                int objCount = list.Count;
                object currentObj;
                Type currentType = list[0].GetType();
                for (int i = 0; i < objCount; i++)
                {
                    currentObj = list[i];

                    //Since the query will return an IEnumarable object so I must use the foreach loop
                    //although I only have one extension method
                    foreach (MethodInfo method in GetExtensionMethods(thisAssembly, currentType))
                    {
                        method.Invoke(null, new object[] { currentObj });
                    }
                }
            }
        }

        static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType)
        {
            var query = from type in assembly.GetTypes()
                        where !type.IsGenericType && !type.IsNested
                        from method in type.GetMethods(BindingFlags.Static
                            | BindingFlags.Public | BindingFlags.NonPublic)
                        where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)
                        where method.GetParameters()[0].ParameterType == extendedType
                        select method;
            return query;
        }

        public static void Save(this Class1 c1)
        {
            Console.WriteLine("Saving C1");
        }
    }   
}


这篇关于使用反射调用扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆