C# 改进性能反射 - 我应该考虑哪些替代方案?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1027980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:52:19  来源:igfitidea点击:

Improving performance reflection - what alternatives should I consider?

c#.netperformancereflection

提问by AndyMM

I need to dynamically set values on a bunch or properties on an object, call it a transmission object.

我需要动态设置对象上的一组值或属性,将其称为传输对象。

There will be a fair number of these transmission objects that will be created and have its properties set in a short space of time. I want to avoid the use of reflection.

将在短时间内创建大量这些传输对象并设置其属性。我想避免使用反射。

Are there alternatives? If so are there sample implementations I could look at?

有替代品吗?如果是这样,是否有我可以查看的示例实现?

采纳答案by Jon Skeet

Use Delegate.CreateDelegateto turn a MethodInfointo a strongly-typed delegate. This can improve performance massively. I have a blog post about thiswith sample code. Note that this is only going to help if you need to set the same properties multiple times - basically it means that a lot of the type checking is done oncewhen you create the delegate, rather than on every invocation.

Delegate.CreateDelegate把一个MethodInfo成一个强类型的代表。这可以大大提高性能。我有一篇关于此示例代码的博客文章。请注意,这只会在您需要多次设置相同的属性时有所帮助 - 基本上这意味着在创建委托时会进行一次类型检查,而不是在每次调用时进行。

Marc Gravell has a HyperPropertyDescriptorproject which achieves even better performance, but introduces an extra dependency. This project became the jumping off point for the more modern Fast Member(github). In general you would use Fast Member over HyperProperty.

Marc Gravell 有一个HyperPropertyDescriptor项目,它实现了更好的性能,但引入了额外的依赖项。这个项目成为更现代的Fast Member( github) 的起点。通常,您将使用 Fast Member 而不是 HyperProperty。

回答by Rex M

Have you established with certainty that using reflection is too slow? Although reflection in .NET is not as fastas static code, it is still extremely fast. You should write the code in the easiest way possible - even if that uses reflection - and only come back to optimize if you notice performance problems and isolate them to your use of reflection. Most of the time, you won't have any problems. Reflection is used in all kinds of performance-sensitive code, such as ASP.NET MVC.

您确定使用反射太慢了吗?尽管 .NET 中的反射不如静态代码,但它仍然非常快。您应该尽可能以最简单的方式编写代码——即使使用反射——并且只有在您注意到性能问题并将它们隔离到您使用反射时才回来进行优化。大多数时候,你不会有任何问题。反射用于各种对性能敏感的代码,例如 ASP.NET MVC。

回答by Otávio Décio

Reflection got a bad rep from Java where it is (or at least used to be) very slow. This is not the case in .net so I don't understand your objection on using it. Also I agree with Rex, you can't say something has poor performance without actually measuring.

反射从 Java 那里得到了一个糟糕的代表,它(或至少曾经是)非常慢。在 .net 中不是这种情况,所以我不明白您对使用它的反对意见。我也同意 Rex 的观点,你不能在没有实际测量的情况下说某些东西的性能很差。

回答by yfeldblum

Reflection can be blazingly fast if you do it right(not as fast as static code, of course).

如果你做得对,反射可以非常快(当然,不如静态代码快)。

Finding a property-setter is slow. Invoking a delegate is fast.

寻找财产设定者很慢。调用委托很快。

You need to get and cache Delegateobjects for each property-setter on each type of DTO. That's the slow part, but it's a one-time hit. Then you can Invokeeach of the cached delegates for the property-setters of a given DTO type, passing in the DTO object and the new property value, but this part will be very fast.

您需要为Delegate每种类型的 DTO 上的每个属性设置器获取和缓存对象。这是缓慢的部分,但它是一次性的。然后,您可以Invoke为给定 DTO 类型的属性设置器的每个缓存委托,传入 DTO 对象和新的属性值,但这部分将非常快。

回答by Marc Gravell

In .NET 4.0 (beta), you can do this with the updated expression trees, using Expression.Blockand Expression.Assign- then compile that to a typed delegate; job done.

在 .NET 4.0(测试版)中,您可以使用更新后的表达式树执行此操作Expression.BlockExpression.Assign然后将其编译为类型化委托;任务完成。

In .NET 2.0 and above (as Jon mentioned) HyperDescriptor is a reasonable option - it works as a custom PropertyDescriptorimplementation, so you just do code like:

在 .NET 2.0 及更高版本(如 Jon 提到的)HyperDescriptor 是一个合理的选择 - 它作为自定义PropertyDescriptor实现工作,因此您只需执行如下代码:

// store this collection for optimum performance
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(
    typeof(SomeType));
props["Name"].SetValue(obj, newName);
props["DateOfBirth"].SetValue(obj, newDoB);

This still has a little boxing, but that isn't actually a bottleneck.

这仍然有一些拳击,但这实际上不是瓶颈。