Если Вы ожидаете нечастые коллизии, , Оптимистичный параллелизм является, вероятно, Вашим лучшим выбором.
Scott Mitchell записал всестороннее учебное руководство при реализации того шаблона:
Оптимистичный параллелизм Реализации
Лямбды отлично подходят для многих сценариев, но если они вам не нужны, может быть, просто не используйте их? Ненавижу это говорить, но простые строки проверены и протестированы, особенно для таких сценариев, как привязка данных. Если вам нужен быстрый доступ, вы можете посмотреть HyperDescriptor, или существуют способы компиляции делегата для методов доступа к свойствам, или вы можете построить Expression
из строки и скомпилировать его (включая приведение к ] объект
, если вам нужна известная подпись, вместо вызова (гораздо более медленного) DynamicInvoke
).
Конечно, в большинстве случаев даже грубое отражение выполняется достаточно быстро, и это не значит узкое место.
Я предлагаю начать с простейшего кода и проверить, что он на самом деле слишком медленный, прежде чем беспокоиться о том, что он будет быстрым. Если он не слишком медленный, не меняйте его. В противном случае сработал бы любой из вышеперечисленных вариантов.
Другая мысль; если вы используете Expression
, вы можете сделать что-то вроде:
public void IncludeProperties<T>(
Expression<Func<T,object>> selectedProperties)
{
// some logic to store parameter
}
IncludeProperties<IUser>( u => new { u.ID, u.LogOnName, u.HashedPassword });
, а затем разобрать выражение? По крайней мере, немного аккуратнее ... вот пример кода, показывающий деконструкцию:
public static void IncludeProperties<T>(
Expression<Func<T, object>> selectedProperties)
{
NewExpression ne = selectedProperties.Body as NewExpression;
if (ne == null) throw new InvalidOperationException(
"Object constructor expected");
foreach (Expression arg in ne.Arguments)
{
MemberExpression me = arg as MemberExpression;
if (me == null || me.Expression != selectedProperties.Parameters[0])
throw new InvalidOperationException(
"Object constructor argument should be a direct member");
Console.WriteLine("Accessing: " + me.Member.Name);
}
}
static void Main()
{
IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword });
}
Как только вы узнаете MemberInfo
( me.Member
выше), создайте свой собственный лямбды для индивидуального доступа должны быть тривиальными. Например (включая приведение к объекту
, чтобы получить единую подпись):
var param = Expression.Parameter(typeof(T), "x");
var memberAccess = Expression.MakeMemberAccess(param, me.Member);
var body = Expression.Convert(memberAccess, typeof(object));
var lambda = Expression.Lambda<Func<T, object>>(body, param);
var func = lambda.Compile();
Вот самое короткое выражение, которое я могу придумать:
public static void IncludeProperties(Expression<Action<IUser>> selectedProperties)
{
// some logic to store parameter
}
public static void S(params object[] props)
{
// dummy method to get to the params syntax
}
[Test]
public void ParamsTest()
{
IncludeProperties(u => S(
u.Id,
u.Name
));
}