MYQueries1 Ответов: 2

Вызов метода с использованием отражения с лучшей производительностью


Я использую метод Invoke для вызова метода с использованием отражения. Производительность эта не велика. Есть ли какое-либо другое решение

Что я уже пробовал:

void ExecuteMethodViaReflection(TestObj comm)
{
    var paramNames = comm.paramNames; //of type string array
    var paramData = comm.Data; //of type Object array

    Type t = this.GetType();
    t.InvokeMember(comm.Method, BindingFlags.InvokeMethod, null, this, paramData, null, null, paramNames);
    }

Dave Kreskowiak

Да, не используй отражение. Это заведомо медленно.

Вам придется описать, почему вы думаете, что вам нужно использовать его в первую очередь.

0x01AA

ха-ха-5!

MYQueries1

Как я могу переписать код, чтобы иметь лучшую производительность. Могу ли я получить небольшой фрагмент кода?

PIEBALDconsult

Используйте отражение, чтобы получить MethodInfo один раз! затем кэшируйте его и используйте много раз.

MYQueries1

Как я могу вызвать метод с параметрами ? если есть методы перегрузки? Можете ли вы опубликовать небольшой фрагмент кода ? Это будет очень полезно

BillWoodruff

Тип t = это.Метод gettype(); а в каком контексте это упоминание здесь ? Как Пегий предлагает кэшировать метод.

Graeme_Grant

Есть лучший способ ... Дженерики и указатели функций на помощь! ;)

2 Ответов

Рейтинг:
2

Mehdi Gholam

Во-первых, не используйте отражение, если оно вам не нужно, и вы знаете, что делаете, поэтому, если количество ваших методов невелико, используйте оператор switch:

switch(comm.Method)
{
    case "method1" : this.Method1(comm.Data); break;
    ...// and so on
}
Вы также можете использовать Dictionary<string, Action> с предварительно заполненными делегатами обработчика методов.

Если вам действительно нужно использовать отражение, то вы должны сначала выяснить, где ваш код медленный, а затем начать кэширование Delegate.CreateDelegate использование Dictionary для более быстрого поиска:

Ускорение отражения вызова C# / .NET-переполнение стека[^]


MYQueries1

Я не могу использовать корпус переключателя здесь, у меня есть функции перегрузки. В это время он может сломаться

Graeme_Grant

Без знания специфики, такой как пример кода методов, которые вы хотите вызвать и в каком контексте, трудно дать лучшие решения. Тем не менее, у меня есть решение, которое я могу опубликовать, как только узнаю больше подробностей. Пожалуйста, нажмите на виджет "улучшить вопрос"и предоставьте информацию. Поэтому удалите тело из выборочных функций, поскольку нам не нужно знать, что они делают, только сигнатуры методов и то, как они вызываются.

Обновление: Проверьте решение №2... Это реальное сравнение того, как это сделать с рефлексией и без нее...

Рейтинг:
0

Graeme_Grant

Расширяя решение Мехди Голама, вот реальный пример того, где метод ProcessFileType "обнаруживает" тип данных, в которые он должен преобразовать, ищет тип данных, затем выполняет преобразование из строки JSON и возвращает структуру класса определенного типа.

// only some types are lists for briefity
private readonly Dictionary<string, Func<JObject, File>> mimeTypes
    = new Dictionary<string, Func<JObject, File>>
{
    { "application/vnd.google-apps.folder", Convert<Folder>() },
    { "image/jpeg", Convert<JpgImage>() },
    { "image/png", Convert<PngImage>() },
    { "application/zip", Convert<Zipped>() },
    { "application/x-zip-compressed", Convert<Zipped>() },
    { "video/mp4", Convert<Mp4Video>() },
    { "text/plain", Convert<TxtDocument>() },
    { "application/vnd.openxmlformats-officedocument.presentationml.presentation",
      Convert<PptDocument>() },
    { "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      Convert<WordDocument>() }
};

// Convert file of type.... mimeTypes
private void ProcessFileType(List<File> results, IList<JObject> jObjs, int i)
{
    var fileToken = jObjs[i].FindTokens("mimeType");
    if (fileToken != null && fileToken.Count > 0)
    {
        var key = mimeTypes.Keys.FirstOrDefault(x => x.Equals(fileToken[0].ToString()));
        if (key != null)
        {
            results.Add(mimeTypes[key](jObjs[i]));
        }
    }
}

// Convert Json Object data into a specified class type
private static Func<JObject, File> Convert<TModel>() where TModel : File
{
    return (jObj) => JsonHelper.ToClass<TModel>(jObj.ToString());
}

Чтобы сделать точно то же самое медленнее, используя отражение, это будет выглядеть примерно так:
public JsonDataTypeConverter()
{
    if (convert == null)
        convert = GetType().GetMethod(nameof(Convert),
                                      BindingFlags.Instance | BindingFlags.NonPublic);
}

private static MethodInfo convert; // configured on class instantiation

// only some types are lists for briefity
private static readonly Dictionary<string, Type> mimeTypes = new Dictionary<string, Type>
{
    { "application/vnd.google-apps.folder", typeof(Folder) },
    { "image/jpeg", typeof(JpgImage) },
    { "image/png", typeof(PngImage) },
    { "application/zip", typeof(Zipped) },
    { "application/x-zip-compressed", typeof(Zipped) },
    { "video/mp4", typeof(Mp4Video) },
    { "text/plain", typeof(TxtDocument) },
    { "application/vnd.openxmlformats-officedocument.presentationml.presentation",
      typeof(PptDocument) },
    { "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      typeof(WordDocument) }
};

// Convert file of type.... mimeTypes
private void ProcessFileType(List<File> results, IList<JObject> jObjs, int i)
{
    var fileToken = jObjs[i].FindTokens("mimeType");
    if (fileToken != null && fileToken.Count > 0)
    {
        var key = mimeTypes.Keys.FirstOrDefault(x => x.Equals(fileToken[0].ToString()));
        if (key != null)
        {
            var method = convert.MakeGenericMethod(new[] { mimeTypes[key] });
            var data = method.Invoke(this, new[] { jObjs[i] });
            results.Add((File)data);
        }
    }
}

// Convert Json Object data into a specified class type
private TModel Convert<TModel>(JObject jObj) where TModel : IResourceKind
{
    return JsonHelper.ToClass<TModel>(jObj.ToString());
}

Если вы хотите увидеть код в действии, вы можете скачать его из этой статьи: Работа с JSON в C# и VB[^] (Пример Google Drive - File Explorer)