długa odpowiedź wymyślanie. Odbicie jest świetne w wielu sytuacjach, w niektórych straszne, ale w prawie wszystkich przypadkach jest powolne.
Istnieją 4 różne sposoby ustawiania właściwości w .NET bez użycia odbicia.
Pomyślałem, że zademonstruję jedno z nich: Używanie skompilowanych drzewek wyrażeń. Zauważ, że budowanie wyrażeń jest również dość drogie, dlatego bardzo ważne jest, aby buforować delegata, który buduje z nim w słowniku (na przykład):
Wyrażenie drzew zostało wprowadzone w .NET35 i jest używane do wielu rzeczy. Używam ich do budowania wyrażenia ustawiającego właściwości, a następnie kompilowania go do delegata.
Przykład pokazuje różne terminy dla różnych przypadków, ale tutaj są moje numery: przypadek sterowania (dysk zakodowany): 0.02s Odbicie: 1.78s Expression Drzewo: 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();
}
}
}
jeśli nie ma naprawdę takie wyrażenie 'dynamicCastedLocaleEntity.GetProperty (wartości [j] .EntityPropertyName) = value;', w jaki sposób środowisko wykonawcze wiedzieć, które instancja, którą chcesz podać wartość? –