使用具有更好性能的反射调用方法 [英] Call method using reflection with better performance

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

问题描述

我使用Invoke方法使用反射调用方法。表现不太好。有没有其他解决方案



我尝试过:



< pre lang =c#> void ExecuteMethodViaReflection(TestObj comm)
{
var paramNames = comm.paramNames; // 类型为字符串数组
var paramData = comm.Data;对象数组类型的 //

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

解决方案

首先不要使用反射,除非你需要它并且你知道你在做什么,所以如果你的方法计数很低使用switch语句:

  switch (comm.Method)
{
case method1 this .Method1(comm.Data); break ;
... // 依此类推
}

您还可以使用预先填充的方法处理程序委托使用字典<字符串,操作>



如果你真的需要使用反射,那么你应该首先找出代码的位置很慢,然后使用 Dictionary Delegate.CreateDelegate c $ c>更快查询:



加速反射调用C#/ .NET - 堆栈溢出 [ ^ ]


扩展Mehdi Gholam的解决方案,以下是方法 ProcessFileType 发现需要转换的数据类型,查找数据类型,然后执行转换来自JSON字符串并返回特定类型的类结构。

  //  只有一些类型是简要列表 
private readonly 字典<字符串,Func< JObject,文件>> mimeTypes
= new Dictionary< string,Func< JObject,File>>
{
{ application / vnd.google-apps.folder,转换< Folder>()},
{ image / jpeg,转换< JpgImage> ;()},
{ image / png,转换< PngImage>() },
{ application / zip,转换< Zipped>()},
{ application / x-zip-compressed,转换< Zipped>()},
{ video / mp4,转换< Mp4Video>()},
{ text / plain,转换< TxtDocument>()},
{< span class =code-string> application / vnd.openxmlformats-officedoc ument.presentationml.presentation
转换< PptDocument>()},
{ application / vnd.openxmlformats-officedocument.wordprocessingml.document
转换< WordDocument>()}
};

// 转换类型的文件.... 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。添加(MIMETYPES [键](jObjs [I]));
}
}
}

// 转换Json将对象数据转换为指定的类类型
private static Func< JObject,文件>转换< TModel>()其中 TModel:文件
{
return (jObj )= > JsonHelper.ToClass< TModel>(jObj.ToString());
}



要使用Reflection执行完全相同的操作,它看起来像这样:

  public  JsonDataTypeConverter()
{
if (convert == < span class =code-keyword> null )
convert = GetType()。GetMethod( nameof (转换),
BindingFlags.Instance | BindingFlags.NonPublic);
}

private static MethodInfo convert; // 在类实例化时配置

// 只有一些类型是简要列表
private static readonly 字典<字符串,类型> mimeTypes = new 字典<字符串,类型>
{
{ application / vnd.google-apps.folder typeof (文件夹)},
{ image / jpeg typeof (JpgImage)},
{ < span class =code-string> image / png, typeof (PngImage)},
{ application / zip typeof (Zipped)},
{ application / x-zip-compressed typeof (Zipped)},
{ video / mp4,< span class =code-keyword> typeof (Mp4Video)},
{ text /纯 typeof (TxtDocument)},
{ application / vnd.openxmlformats-officedocument.presentationml.presentation
typeof (PptDocument)},
{< span class =code-string> application / vnd.openxmlformats-officedocument.wordprocessingml.document
typeof (WordDocument)}
};

// 转换类型的文件.... 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 [] {m​​imeTypes [key]});
var data = method.Invoke( this new [] {jObjs [i]});
results.Add((File)data);
}
}
}

// 转换Json将对象数据转换为指定的类类型
private TModel转换< TModel>(JObject jObj)其中 TModel:IResourceKind
{
return JsonHelper.ToClass< TModel>(jObj.ToString());
}



如果您想查看代码的实际应用,可以从本文下载:在C#中使用JSON& VB [ ^ ](Google云端硬盘 - 文件资源管理器示例)


I am using the Invoke method to call method using reflection. Performance of this not great. Is there any other solution

What I have tried:

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);
    }

解决方案

First don't use reflection unless you need it and you know what you are doing, so if your method counts is low use a switch statement:

switch(comm.Method)
{
    case "method1" : this.Method1(comm.Data); break;
    ...// and so on
}

You can also use a Dictionary<string, Action> with pre-populated method handler delegates.

If you really need to use reflection then you should first find out where you code is slow then start caching the Delegate.CreateDelegate using a Dictionary for faster lookup:

Speeding up Reflection Invoke C#/.NET - Stack Overflow[^]


Expanding on Mehdi Gholam's solution, here is a real-life example of where the method ProcessFileType "discovers" the type of data that it needs to convert to, looks up the type of data, then executes the conversion from JSON string and returns a class structure of a specific type.

// 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());
}


To do exactly the same thing slower using Reflection, it would look something like this:

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());
}


If you want to see the code in action, you can download it from this article: Working with JSON in C# & VB[^] (Google Drive - File Explorer example)


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

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