Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.06.16 14:18
Оценка:
Здравствуйте, Serginio1, Вы писали:


Попробовал вызвать CoreCLr из натива.

создал тестовый класс
using System;
using System.Collections.Generic;
using System.Reflection;

namespace CoreClrDLL
{
    public class Program
    {
        public static object ExecuteMethod(object objOrig, string MethodName, params object[] argsOrig)
        {
            object res = null;

            Type T = objOrig.GetType();

            var list = new List<Type>();

            foreach (var obj in argsOrig)
                list.Add(obj.GetType());

            var Method = T.GetMethod(MethodName, list.ToArray());

            res = Method.Invoke(objOrig, argsOrig);

            return res;

        }


        public static int TestFunction(int i)
        {


            var rn = new Random(i);

            //   int res = rn.Next(10000);
            int res = (int)ExecuteMethod(rn, "Next", 10000);

            return res;

        }
    }
}

Пример взял отсюда http://www.fancy-development.net/hosting-net-core-clr-in-your-own-process

И соответственно вызов
typedef int (STDMETHODCALLTYPE *ManagedMethod)(int); 
HRESULT  CreateDelegate2(ICLRRuntimeHost2* pCLRRuntimeHost, DWORD appDomainID, wstring AssemblyName, wstring ClassName, wstring MethodName, INT_PTR *fnPtr) 
{ 

    HRESULT    hr = pCLRRuntimeHost->CreateDelegate( 
        appDomainID, 
        AssemblyName.c_str(), 
        ClassName.c_str(), 
        MethodName.c_str(), 
        (INT_PTR*)fnPtr); 

    return hr; 

}

И вызов
ManagedMethod pTestFunction; 

    hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestFunction", (INT_PTR*)&pTestFunction); 
    if (FAILED(hr)) 
    { 
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr); 

    } 
    else 
    printf_s("result method  pTestFunction(555) : (%d).\n", pTestFunction(555));

Нет InvokeMember придется вручную искать перегруженную функцию.

Вобщем оболочку можно сделать
и солнце б утром не вставало, когда бы не было меня
Re[2]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 06:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Нет InvokeMember придется вручную искать перегруженную функцию.


S>Вобщем оболочку можно сделать


InvokeMember брал на себя поиск нужного метода и передачу параметров params.
И соответственно встал вопрос как искать подходящий метод.
1. Когда один из параметров null
Каков приоритет типов?
2. Кода есть params
Сначала идут методы с большим количеством параметров?
и солнце б утром не вставало, когда бы не было меня
Re[3]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 11:04
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> InvokeMember брал на себя поиск нужного метода и передачу параметров params.

S>И соответственно встал вопрос как искать подходящий метод.

Для начала лучше перетащить разруливание перегрузок в managed-код. Дальше проще и зависит от задачи.

Подобрать перегрузку, зная типы аргументов? type.GetMethod("name", bindingFlags, argTypes) или как-то так.

Известны только значения? Пишем вызов любого метода через dynamic, с помошью декомпилятора смотрим что за код генерится под капотом, повторяем вручную. Ключевые слова для поиска — CallSite<T>, CallSiteBinder.

Первое попавшееся: https://habrahabr.ru/post/144330/
Re[4]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 11:27
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> InvokeMember брал на себя поиск нужного метода и передачу параметров params.

S>>И соответственно встал вопрос как искать подходящий метод.

S>Для начала лучше перетащить разруливание перегрузок в managed-код. Дальше проще и зависит от задачи.


S>Подобрать перегрузку, зная типы аргументов? type.GetMethod("name", bindingFlags, argTypes) или как-то так.


S>Известны только значения? Пишем вызов любого метода через dynamic, с помошью декомпилятора смотрим что за код генерится под капотом, повторяем вручную. Ключевые слова для поиска — CallSite<T>, CallSiteBinder.


S>Первое попавшееся: https://habrahabr.ru/post/144330/


Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

То есть использование любых сборок из Натива. Например http://ru.stackoverflow.com/questions/532477/%d0%9f%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4%d0%bf%d0%b8%d1%81%d0%b8-%d0%ad%d0%a6%d0%9f-%d0%b2-%d1%84%d0%b0%d0%b9%d0%bb%d0%b5-online-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d1%81%d0%b5%d1%80%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%b0-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-c-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d0%b1%d0%b8%d0%b1

Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.
Соответственно я не знаю, что и как будет вызываться, но динамически я должен найти самый подходящий перегруженный метод.

Например есть две функции

void Метод(int парам, string str)
 void Метод(int парам, object str)

При вызове Метод(1,null) какой метод выбрать?

С параметрами массивами
void Метод(int парам, params object[] str)
void Метод(int парам,int пара2, object str)

Метод(1,1,6)

Кстати в Core .Net много отличий. Например во взрослом
public abstract object[] GetCustomAttributes(
    Type attributeType,
    bool inherit
)


То в Core все через расширения
public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element, Type attributeType, bool inherit);


Так на просторах нашел


public static object call(MethodInfo Method, object Target, params object[] input)
        {

   
            ParameterInfo[] parameters = Method.GetParameters();
            bool hasParams = false;
            if (parameters.Length > 0)
                hasParams = parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), false).GetEnumerator().MoveNext();

            if (hasParams)
            {
                int lastParamPosition = parameters.Length - 1;

                object[] realParams = new object[parameters.Length];
                for (int i = 0; i < lastParamPosition; i++)
                    realParams[i] = input[i];

                Type paramsType = parameters[lastParamPosition].ParameterType.GetElementType();
                Array extra = Array.CreateInstance(paramsType, input.Length - lastParamPosition);
                for (int i = 0; i < extra.Length; i++)
                    extra.SetValue(input[i + lastParamPosition], i);

                realParams[lastParamPosition] = extra;

                input = realParams;
            }

            return Method.Invoke(Target, input);
        }


Но нужно смотреть на Out и Ref параметры.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 07.06.2016 12:51 Serginio1 . Предыдущая версия .
Re[5]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 13:32
Оценка: 12 (1)
Здравствуйте, Serginio1, Вы писали:


S> Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

А тут не имеет значения, что вы хотите. Важно только то, что поддерживается, т.е. C-style ABIs. Зачатки COM Interop есть, но только под win.
Нужно что-то более изощрённое — придётся изобретать магию самому, что требует досконального знания как нативной части, так и кишков маршаллинга CoreCLR. Я, к примеру, за это не возьмусь, т.к. только на поверхностное изучение минимум пару недель придётся потратить.


S> То есть использование любых сборок из Натива.

В общем случае нереально. Не, если ограничиться структурами / делегатами и следить за временем жизни ссылок, то что-то может и получиться, но на "любых сборок" я бы не рассчитывал. Вам точно не достаточно того, что есть в оф.справке, секция "Invoking managed code from unmanaged code"?

Если что, даже менее амбициозные замашки на c++ выглядят как-то так.

S> Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.

Нельзя просто так взять и перенести COM на платформу, которая его не поддерживает. Ваш кэп


S>При вызове Метод(1,null) какой метод выбрать?

Простой способ: AmbigiousMatchException
Сложный способ — подрубаем DLR, как советовал выше

S>То в Core все через расширения

Core как такового нет. Есть RC, которое, как ВНЕЗАПНО выяснилось, несовместимо с 99% существующего кода и невнятные обещания binary compatibility для основных классов BCL, включая reflection.

Я бы не заморачивался с как минимум до следующего релиза. Если конечно нет желания оседлать хайп и снять все сливки Риски соответствующие.
Re[6]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 14:35
Оценка: 21 (1)
Здравствуйте, Sinix, Вы писали:

S> Здравствуйте, Serginio1, Вы писали:



S>> Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

S>А тут не имеет значения, что вы хотите. Важно только то, что поддерживается, т.е. C-style ABIs. Зачатки COM Interop есть, но только под win.
S>Нужно что-то более изощрённое — придётся изобретать магию самому, что требует досконального знания как нативной части, так и кишков маршаллинга CoreCLR. Я, к примеру, за это не возьмусь, т.к. только на поверхностное изучение минимум пару недель придётся потратить.


S>> То есть использование любых сборок из Натива.

S>В общем случае нереально. Не, если ограничиться структурами / делегатами и следить за временем жизни ссылок, то что-то может и получиться, но на "любых сборок" я бы не рассчитывал. Вам точно не достаточно того, что есть в оф.справке, секция "Invoking managed code from unmanaged code"?

Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод
bool CAddInNative::CallAsFunc(const long lMethodNum,
                tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{ 
    return false; 
}


Через IntPtr зная структуры я могу распаковать параметры (Marshal)в том числе и индексы на Объекты. А память для строк byte[] я могу на стороне .Net получив ссылку на метод.
Могу просто все запаковывать в масив.
Меня сейчас просто волнуют приоритеты перегруженных методов. Но могу не заморачиваться пока и выбирать подходящий метод



S>Если что, даже менее амбициозные замашки на c++ выглядят как-то так.


S>> Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.

S>Нельзя просто так взять и перенести COM на платформу, которая его не поддерживает. Ваш кэп

Был такой компонет TSocketConnection в Delphi. Суть его в том, что это была замена DCOM. Дам используя IDispatch данные упаковывались в массив. Ссылки на объекты на стороне сервера упаковывались в Idispatch и маршалились обратно. Все это реализуема на уровне собственного маршалинга.

S>>При вызове Метод(1,null) какой метод выбрать?

S>Простой способ: AmbigiousMatchException
S>Сложный способ — подрубаем DLR, как советовал выше
DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>>То в Core все через расширения

S>Core как такового нет. Есть RC, которое, как ВНЕЗАПНО выяснилось, несовместимо с 99% существующего кода и невнятные обещания binary compatibility для основных классов BCL, включая reflection.
Ну Method.Invoke(); и


Type T = typeof(string);

var Method = T.GetMethod("Format",new Type[]{ T,  typeof(Object[])});


Работают.
S>Я бы не заморачивался с как минимум до следующего релиза. Если конечно нет желания оседлать хайп и снять все сливки Риски соответствующие.

Ну мне еще C++ нужно изучить, а заодно напишу аналог InvokeMember
и солнце б утром не вставало, когда бы не было меня
Re[7]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 14:48
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>> То есть использование любых сборок из Натива.

S>>В общем случае нереально.
S> Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод

Оно будет работать или для вызовов managed->native, или для случаев, когда объекты живут не дольше, чем время вызова native->managed. Иначе получаем или утечку объектов на managed-стороне, или порчу памяти из-за пожраного GC объекта, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).

Довольно существенное ограничение.

Если устраивает — всё сводится к получить на managed-стороне массив объектов-параметров + тип + имя метода. Дальше всё как в первом ответе написал, второй вариант.

S> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.
Re[8]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 15:06
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>> То есть использование любых сборок из Натива.

S>>>В общем случае нереально.
S>> Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод

S>Оно будет работать или для вызовов managed->native, или для случаев, когда объекты живут не дольше, чем время вызова native->managed. Иначе получаем или утечку объектов на managed-стороне, или порчу памяти из-за пожраного GC объекта, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).


Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

На стороне 1С есть подсчет ссылок и Done() при разрушении объекта, которое я могу ипользовать для удаления из массива.

Кроме того можно освобождать все ссылки при разрушении домена

pCLRRuntimeHost->UnloadAppDomain(domainId, true);

    // Stop the runtime host
    pCLRRuntimeHost->Stop();


S>Довольно существенное ограничение.


S>Если устраивает — всё сводится к получить на managed-стороне массив объектов-параметров + тип + имя метода. Дальше всё как в первом ответе написал, второй вариант.


S>> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

Кстати попробовал на стороне Манагед


public static int TestFunctionIntPtr(IntPtr i)
        {


            
            int res = Marshal.ReadInt32(i);

            return res;

        }



И вызов

typedef int (STDMETHODCALLTYPE *ManagedMethodIntPtr)(int*);

ManagedMethodIntPtr pTestFunctionIntPtr;
    //TestFunctionIntPtr

    hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestFunctionIntPtr", (INT_PTR*)&pTestFunctionIntPtr);
    if (FAILED(hr))
    {
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr);

    }
    else
    {
        cout << "Press Key";
        cin.get();
        int i = 555;
        printf_s("result method  pTestFunctionIntPtr(555) : (%d).\n", pTestFunctionIntPtr(&i));
    }


Marshal такой же как и во взрослом. А значит могу ползать по памяти как хочу.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 07.06.2016 15:09 Serginio1 . Предыдущая версия .
Re[8]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 18:22
Оценка: :)
Здравствуйте, Sinix, Вы писали:



S>> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.
Ну самом деле в DLR строится дерево и компилится. Это нормально, когда известны методы, сигнатура они известны на этапе компиляции.
А вот в моем случае вообще ничего неизвестно.
Но это не большая беда, так как я могу получить используемые типы. Просто нужны правила для приоритетов.
То есть методы я могу отсортировать по признаку есть params или нет, ну и по количеству параметров.
Сначала отбираются без params, если не находятся, то выбираются от большего к меньшему с params.

А, что касается null, то случайным образом из доступных ссылочных типов или Nullable
и солнце б утром не вставало, когда бы не было меня
Re[9]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 06:16
Оценка: 15 (2) +1
Здравствуйте, Serginio1, Вы писали:

S> Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

Ну, т.е. как и говорил, получаем или утечку объектов на managed-стороне, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).
Для сложных графов с изменяемыми свойствами-объектами тесты как минимум надо сделать

S>>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

S> DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

Вот народ я с вас фигею. Вам дают карту с сокровищами, а вы требуете чтоб вас экспрессом минуя все три тома приключений доставили прямо в термал спа "Золотое кольцо" (магнитик на холодильник с Балрогом в подарок). Где ваша это... мазохизм? Стремление усложнить жизнь? Граблефилия? А, авантюризм, во!

Держите, скучный вы человек:
        private static CallSite<Action<CallSite, Type, object, object>> callSite;

        static void Main(string[] args)
        {
            CallADynamic(1, 2);
            CallADynamic(null, null);
            CallADynamic(null, new object());
        }

        private static void CallADynamic(params object[] data)
        {
            if (callSite == null)
            {
                callSite =
                    CallSite<Action<CallSite, Type, object, object>>.Create(
                        Binder.InvokeMember(
                            CSharpBinderFlags.ResultDiscarded,
                            "CallA", null, typeof(Program), new CSharpArgumentInfo[]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));
            }
            callSite.Target(callSite, typeof(Program), data[0], data[1]);
        }

        static void CallA(params int[] args)
        {
            Console.WriteLine("params");
        }

        static void CallA(object a, object b)
        {
            Console.WriteLine("objects");
        }

        static void CallA(object a, string b)
        {
            Console.WriteLine("object+string");
        }


Как допилить до вызова произвольного метода — сами-сами. Иначе вообще никакого удовольствия не будет.

  P.S.
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 06:51
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

S>Ну, т.е. как и говорил, получаем или утечку объектов на managed-стороне, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).
S>Для сложных графов с изменяемыми свойствами-объектами тесты как минимум надо сделать

Опять не читаешь. На стороне 1С есть подсчет ссылок и Done при разрушении.
Кроме того могу выгрузить домен.

S>>>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

S>> DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

S>Вот народ я с вас фигею. Вам дают карту с сокровищами, а вы требуете чтоб вас экспрессом минуя все три тома приключений доставили прямо в термал спа "Золотое кольцо" (магнитик на холодильник с Балрогом в подарок). Где ваша это... мазохизм? Стремление усложнить жизнь? Граблефилия? А, авантюризм, во!


S>Держите, скучный вы человек:

S>
S>        private static CallSite<Action<CallSite, Type, object, object>> callSite;

S>        static void Main(string[] args)
S>        {
S>            CallADynamic(1, 2);
S>            CallADynamic(null, null);
S>            CallADynamic(null, new object());
S>        }

S>        private static void CallADynamic(params object[] data)
S>        {
S>            if (callSite == null)
S>            {
S>                callSite =
S>                    CallSite<Action<CallSite, Type, object, object>>.Create(
S>                        Binder.InvokeMember(
S>                            CSharpBinderFlags.ResultDiscarded,
S>                            "CallA", null, typeof(Program), new CSharpArgumentInfo[]
S>                            {
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
S>                            }));
S>            }
S>            callSite.Target(callSite, typeof(Program), data[0], data[1]);
S>        }

S>        static void CallA(params int[] args)
S>        {
S>            Console.WriteLine("params");
S>        }

S>        static void CallA(object a, object b)
S>        {
S>            Console.WriteLine("objects");
S>        }

S>        static void CallA(object a, string b)
S>        {
S>            Console.WriteLine("object+string");
S>        }
S>


S>Как допилить до вызова произвольного метода — сами-сами. Иначе вообще никакого удовольствия не будет.


S>
  P.S.


Спасибо! Веселый Вы наш. Но возникают вопросы.

Я так понимаю, что можно создать Кучу CallSite<Action<CallSite, Type, object, object>>
По количеству аргументов и использовать их?
И получается для каждого вызова я должен создавать свой callSite по имени метода, типу и количеству агрументов.
Сейчас проверю кстати код на CoreClr.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 08.06.2016 7:28 Serginio1 . Предыдущая версия . Еще …
Отредактировано 08.06.2016 7:07 Serginio1 . Предыдущая версия .
Re[11]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 07:13
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>1. CallSite под определенную сигнатуру (CallSite<Action<CallSite, Type, object, object>> )

Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>2. Как определить с params (удобно передавать без массива)

Не, ну до такой степени лениться — это уже перебор Первый вызов в примере.

S>3. Каково время на компиляцию если для каждого вызова нужно создавать CallSite?

Хитрый план:
1. Взять штуку, которая используется под капотом IronPython/IronRuby/прочих динамических языков под CLR.
2. Подозревать, что оно может тормозить.


Не для каждого, а для первого. CallSite кэширует сгенеренные делегаты.


S> Пока это мало чем отличается от T.GetMethod(имяМетода,Type[] типы);

Не вопрос, как сделаете корректное разруливание перегрузок по значениям аргументов в GetMethod() — так сразу и приходите.

P.S. И чистите при ответе оверквотинг Глаза же вылазят.
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 07:38
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>1. CallSite под определенную сигнатуру (CallSite<Action<CallSite, Type, object, object>> )

S>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().
У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
В DLR уже заранее известно и имя метода и количество параметров.
Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.
Кстати возможно, что при вызове GetMethods они идут уже в приоритетно порядке. Посмотрю.



S>>2. Как определить с params (удобно передавать без массива)


S>Не, ну до такой степени лениться — это уже перебор Первый вызов в примере.

Прошу прощения. Я уже подправил ответ.

S>>3. Каково время на компиляцию если для каждого вызова нужно создавать CallSite?

S>Хитрый план:
S>1. Взять штуку, которая используется под капотом IronPython/IronRuby/прочих динамических языков под CLR.
S>2. Подозревать, что оно может тормозить.
S>

S>Не для каждого, а для первого. CallSite кэширует сгенеренные делегаты.

Ну у меня то может быть всего один раз.


S>> Пока это мало чем отличается от T.GetMethod(имяМетода,Type[] типы);

S>Не вопрос, как сделаете корректное разруливание перегрузок по значениям аргументов в GetMethod() — так сразу и приходите.
Да там не так и сложно. Если GetMethods() выдает по приоритету.

S>P.S. И чистите при ответе оверквотинг Глаза же вылазят.

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

Проверил на CoreNet. Работает

params
object+string
objects
и солнце б утром не вставало, когда бы не было меня
Re[13]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 07:57
Оценка: +2
Здравствуйте, Serginio1, Вы писали:

S>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.


S>В DLR уже заранее известно и имя метода и количество параметров.

S> Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
S>Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.

Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

Оптимизм это конечно хорошо, но только при условии, что человек ориентируется в матчасти.
Иначе получается что-то в духе "хочу сделать свою СУБД. Логика и приоритеты понятны, так что проблем не будет."
Оно с одной стороны забавно, с другой — представляешь, сколько времени будет убито впустую чисто из-за нежелания разобраться в вопросе и уже не смешно.
Re[14]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 08:35
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
S>В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.
Это я понимаю. Вопрос что выгоднее сделать универсальный поиск метода или генерить в рантайме калсайты.

S>>В DLR уже заранее известно и имя метода и количество параметров.

S>> Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
S>>Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.

S>Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

Согласен. Но она существует.

S>Оптимизм это конечно хорошо, но только при условии, что человек ориентируется в матчасти.

S>Иначе получается что-то в духе "хочу сделать свою СУБД. Логика и приоритеты понятны, так что проблем не будет."
S>Оно с одной стороны забавно, с другой — представляешь, сколько времени будет убито впустую чисто из-за нежелания разобраться в вопросе и уже не смешно.
Но и твое предложение не совсем удобно. Практический на каждый вызов я должен создавать привязку.
Хотя можно ограничится и 16 параметрами. Надо посмотреть на производительность и для каждого типа кэшировать методы по имени метода и количеству параметров.
Спасибо!
и солнце б утром не вставало, когда бы не было меня
Re[14]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 09:40
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
S>В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.

Значит я могу нагенерировать методы

public static CallSite<Func<CallSite, Type, object, object, object>>  CallADynamic2Params(string MethodName)
        {
            
             var   res =
                    CallSite<Func<CallSite, Type, object, object, object>>.Create(
                        Binder.InvokeMember(
                            CSharpBinderFlags.ResultDiscarded,
                            MethodName,null, typeof(Program),  new CSharpArgumentInfo[]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));

            return res;
        }

        public static object CallFor2Param(Type type, object DynamicCalSite, params object[] data)
        {
            var cS = (CallSite<Func<CallSite, Type, object, object, object>>)DynamicCalSite;
            return cS.Target(cS, type, data[0], data[1]);


        }



Сохранять CallSite для типа по имени и количеству параметров.

и вызывать


var callSite = DynamicCall.CallADynamic2Params("CallA");

            DynamicCall.CallFor2Param(typeof(DynamicCall),callSite,1, 2);
            DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, null, null);
            DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, null, new object());

            double d = 78;
            var obj1 = DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, 1, d);



А можно еще нескромный вопрос.
Это для статических методов. А как для объектов?
и солнце б утром не вставало, когда бы не было меня
Re[15]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 09:45
Оценка: 18 (2) +1
Здравствуйте, Serginio1, Вы писали:

S> Это я понимаю. Вопрос что выгоднее сделать универсальный поиск метода или генерить в рантайме калсайты.

Вопрос из серии "сделать универсальный транслятор sql-запросов или просто подключить EF?"


S>>Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

S> Согласен. Но она существует.
Это не значит, что её легко повторить


S> Но и твое предложение не совсем удобно. Практический на каждый вызов я должен создавать привязку.


"И конфеты за меня есть будете? — Ага!". Ну и далее по тексту. Раз сами просите — вот вам: убийца -- садовник. Эхх, такую интригу убили...
Отредактировано 08.06.2016 9:48 Sinix . Предыдущая версия .
Re[16]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 10:01
Оценка:
Здравствуйте, Sinix, Вы писали:


S>"И конфеты за меня есть будете? — Ага!". Ну и далее по тексту. Раз сами просите — вот вам: убийца -- садовник. Эхх, такую интригу убили...


Вот уж наиогромнейшее спасибо!
Пошел проверять после обеда.
и солнце б утром не вставало, когда бы не было меня
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 11:02
Оценка:
Здравствуйте, Sinix, Вы писали:

Есть проблема с ref

Сделать такой метод
static public int CallA(ref int a, double b)
        {
            a = 9;
            SB.AppendLine("ref int+double");
            return 9;
        }


То он невидим. Если добавить |CSharpArgumentInfoFlags.IsRef
Cannot convert type 'object' to 'ref int'
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.