Lambda sono grandi per molti scenari - ma se non li vogliono, forse semplicemente non li usano? Odio dirlo, ma stringhe semplici sono provate e testate, specialmente per scenari come l'associazione dati. Se si desidera un accesso rapido, è possibile esaminare HyperDescriptor oppure esistono modi per compilare un delegato per gli accessor della proprietà oppure è possibile creare uno Expression
dalla stringa e compilarlo (incluso un cast su object
se si desidera una firma nota, piuttosto che chiamare il (molto più lento) DynamicInvoke
).
Naturalmente, nella maggior parte dei casi anche la riflessione approssimativa è abbastanza veloce e non è il collo di bottiglia.
Suggerisco di iniziare con il codice più semplice e controllare che sia effettivamente troppo lento prima di preoccuparsi che sia veloce. Se non è troppo lento, non cambiarlo. Qualsiasi delle opzioni di cui sopra avrebbe funzionato diversamente.
Un'altra riflessione; se si utilizza Expression
, si potrebbe fare qualcosa di simile:
public void IncludeProperties<T>(
Expression<Func<T,object>> selectedProperties)
{
// some logic to store parameter
}
IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword });
e poi prendere l'espressione a parte? Un po 'più ordinato, almeno ... ecco alcuni esempi di codice che mostra la decostruzione:
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 });
}
Una volta che conosci le MemberInfo
s (me.Member
in precedenza), costruire il proprio lambda per l'accesso individuale dovrebbe essere banale. Per esempio (tra cui un cast di object
per ottenere una firma singola):
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();
oooh, nice one :) –
Qual è il modo migliore per mantenere le proprietà selezionate per l'accesso rapido? Lista? –
'MemberInfo' andrebbe bene; 'Func' (o 'Func ') andrebbe bene; un 'PropertyDescriptor' andrebbe bene (specialmente con HyperDescriptor). Funzionerà in entrambi i modi ... –