Re[13]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.06.16 07:43
Оценка:
Здравствуйте, Serginio1, Вы писали:

Вобщем добавил код. Вроде работает

namespace CoreClrDLL
{

    public class СравнительМетодов<T> : IComparer<ИнфoрмацияОМетоде<T>>   where T : MethodBase
    {


        public int Compare(ИнфoрмацияОМетоде<T> A, ИнфoрмацияОМетоде<T> B)
        {
            int res = 0;
            for (int i=0; i< A.Параметры.Count(); i++)
            {

                res = A.Параметры[i].CompareTo(B.Параметры[i]);

                if (res != 0) return res;
            }

            res = A.hasParams.CompareTo(B.hasParams);

            if (res != 0) return res;


            res = -A.КоличествоПараметровПарамс.CompareTo(B.КоличествоПараметровПарамс);
            if (res != 0) return res;

            return A.Method.ToString().CompareTo(B.Method.ToString());
        }


       
    }

    public class СравнительМетодовСпарамс<T> : IComparer<ИнфoрмацияОМетоде<T>> where T : MethodBase
    {


        public int Compare(ИнфoрмацияОМетоде<T> A, ИнфoрмацияОМетоде<T> B)
        {


            int res = 0;
            res = -A.КоличествоПараметров.CompareTo(B.КоличествоПараметров);
            if (res != 0) return res;

            for (int i = 0; i < A.Параметры.Count() - 1; i++)
            {

                res = A.Параметры[i].CompareTo(B.Параметры[i]);

                if (res != 0) return res;
            }

            res = A.hasParams.CompareTo(B.hasParams);

            if (res != 0) return res;


           

            return A.Method.ToString().CompareTo(B.Method.ToString());
        }
    }
    public class ВсеМетодыПоИмени<T> where T : MethodBase
    {
         Dictionary<int, List<ИнфoрмацияОМетоде<T>>> ОбычныеМетоды=new Dictionary<int, List<ИнфoрмацияОМетоде<T>>>();

         List<ИнфoрмацияОМетоде<T>> МетодыСParams=new List<ИнфoрмацияОМетоде<T>>();

        void ДобавитьВСловарь(ИнфoрмацияОМетоде<T> им, int КоличествоПараметров)
        {
            List<ИнфoрмацияОМетоде <T>> СписокМетодов = null;

            if (!ОбычныеМетоды.TryGetValue(КоличествоПараметров, out СписокМетодов))
            {
                СписокМетодов = new List<ИнфoрмацияОМетоде<T>>();
                ОбычныеМетоды[КоличествоПараметров] = СписокМетодов;


            }


            СписокМетодов.Add(им);
        }

        void ДобавитПарамсВСписок(KeyValuePair<int, List<ИнфoрмацияОМетоде<T>>>[] Массив, ИнфoрмацияОМетоде<T> Им)
        {
            int минКолПарам = Им.КоличествоПараметров - 1;

            
            foreach (var кв in Массив)
            {

                if (кв.Key < минКолПарам) continue;


                var им = new ИнфoрмацияОМетоде<T>(Им, кв.Key);
                кв.Value.Add(им);

            }

        }
        void ДобавитьМетодыСпарамсВОбычныеМетоды()
        {

            var KV = ОбычныеМетоды.OrderBy(x => x.Key).ToArray();
            foreach (var им in МетодыСParams)
            {

                ДобавитПарамсВСписок(KV, им);


            }

            foreach (var kv in KV)
            {
                kv.Value.Sort(new СравнительМетодов<T>());

            }
        }
        public ВсеМетодыПоИмени(IEnumerable<T> методы)
        {

            foreach(var метод in методы)
            {

                var им = new ИнфoрмацияОМетоде<T>(метод);

                if (им.hasParams)
                {
                    МетодыСParams.Add(им);
                    var ОбычныйМетод = new ИнфoрмацияОМетоде<T>(им);
                    ДобавитьВСловарь(ОбычныйМетод, ОбычныйМетод.КоличествоПараметров);
                }
                else
                {

                    ДобавитьВСловарь(им, им.КоличествоПараметров);
                }

            }


            ДобавитьМетодыСпарамсВОбычныеМетоды();

            МетодыСParams.Sort(new СравнительМетодовСпарамс<T>());

         

        }

        public ИнфoрмацияОМетоде<T> НайтиМетод(object[] параметрыОбъекты)
        {

            Type[] параметры = new Type[параметрыОбъекты.Length];

            for (var i=0; i< параметрыОбъекты.Length; i++)
            {
                if (параметрыОбъекты[i] == null)
                    параметры[i] = null;
                else
                    параметры[i] = параметрыОбъекты[i].GetType();


            }
            List<ИнфoрмацияОМетоде<T>> СписокМетодов;

            if (ОбычныеМетоды.TryGetValue(параметры.Length, out СписокМетодов))
            {
                if (параметры.Length == 0) return СписокМетодов[0];

                foreach (var метод in СписокМетодов)
                {
                    if (метод.Сравнить(параметры))
                        return метод;

                }


            }


            foreach (var метод in МетодыСParams)
            {
                if (метод.СравнитьПарамс(параметры))
                    return метод;

            }

            return null;
        }
    }
}



И вызов



public static void НайтиИВыполнитьМетод(ВсеМетодыПоИмени<MethodInfo> ВсеМетоды, params object[] параметры)
        {
            var метод = ВсеМетоды.НайтиМетод(параметры);
            if (метод != null)
                   метод.ВыполнитьМетод(null, параметры);

        }
        public static void ТестПоискаМетода()
        {

            DynamicCall.SB.Clear();
            var методы = typeof(DynamicCall).GetMethods().Where(x => x.Name == "CallA").ToArray();

            var всеМетоды = new ВсеМетодыПоИмени<MethodInfo>(методы);
            //DynamicCall.CallADynamic(1, 2);
            //DynamicCall.CallADynamic(null, null);
            //DynamicCall.CallADynamic(null, new object());

            double d = 6;
            НайтиИВыполнитьМетод(всеМетоды, 2, d);
            НайтиИВыполнитьМетод(всеМетоды, 1, 2);
            НайтиИВыполнитьМетод(всеМетоды, null, null);
            НайтиИВыполнитьМетод(всеМетоды, null, new object());
            НайтиИВыполнитьМетод(всеМетоды, 1, new int[] { 1,2,3});

            string ss = DynamicCall.SB.ToString();
        }



Выдает

ref int+double
int+params
object+string
objects
int+params
и солнце б утром не вставало, когда бы не было меня
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.