Respuesta larga que viene. La reflexión es excelente en muchas situaciones, horrible en algunos, pero en casi todos los casos es lenta.
Hay al menos 4 maneras diferentes de establecer una propiedad en .NET sin tener que usar la reflexión.
Creo que demuestro una de ellas: Usar árboles de expresiones compiladas. Tenga en cuenta que la creación de expresiones también es bastante costosa, por eso es muy importante almacenar en caché el delegado que se compila con él en un diccionario (por ejemplo):
Expression Trees se introdujo en .NET35 y se usa para muchas cosas. Aquí los uso para construir una expresión de establecimiento de propiedades y luego compilarla en un delegado.
El ejemplo demuestra un calendario diferente para los diferentes casos, pero aquí están mis números: caso de control (no modificable): 0.02s Reflexión: 1.78s árbol Expresión: 0.06s
using System;
using System.Linq.Expressions;
namespace DifferentPropertSetterStrategies
{
class TestClass
{
public string XY
{
get;
set;
}
}
class DelegateFactory
{
public static Action<object, object> GenerateSetPropertyActionForControl(
)
{
return (inst, val) => ((TestClass) inst).XY = (string) val;
}
public static Action<object, object> GenerateSetPropertyActionWithReflection(
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
return (inst, val) => propertyInfo.SetValue (inst, val, null);
}
public static Action<object,object> GenerateSetPropertyActionWithLinqExpression (
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
var propertyType = propertyInfo.PropertyType;
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var valueParameter = Expression.Parameter(typeof(object), "value");
var lambda = Expression.Lambda<Action<object, object>> (
Expression.Assign (
Expression.Property (Expression.Convert (instanceParameter, type), propertyInfo),
Expression.Convert(valueParameter, propertyType)),
instanceParameter,
valueParameter
);
return lambda.Compile();
}
}
static class Program
{
static void Time (
string tag,
object instance,
object value,
Action<object, object > action
)
{
// Cold run
action(instance, value);
var then = DateTime.Now;
const int Count = 2000000;
for (var iter = 0; iter < Count; ++iter)
{
action (instance, value);
}
var diff = DateTime.Now - then;
Console.WriteLine ("{0} {1} times - {2:0.00}s", tag, Count, diff.TotalSeconds);
}
static void Main(string[] args)
{
var instance = new TestClass();
var instanceType = instance.GetType();
const string TestProperty = "XY";
const string TestValue = "Test";
// Control case which just uses a hard coded delegate
Time(
"Control",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionForControl()
);
Time(
"Reflection",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithReflection (instanceType, TestProperty)
);
Time(
"Expression Trees",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithLinqExpression(instanceType, TestProperty)
);
Console.ReadKey();
}
}
}
si realmente hay una expresión 'tales dynamicCastedLocaleEntity.GetProperty (valores [j] .EntityPropertyName) = valor;', ¿Cómo sabe el tiempo de ejecución que instancia que desea dar el valor? –