2012-03-08 8 views
11

Come convertire PropertyInfo in espressione di proprietà che può essere utilizzata per richiamare il metodo StructuralTypeConfiguration<TStructuralType>.Ignore<TProperty>(Expression<Func<TStructuralType, TProperty>> propertyExpression)?Come convertire PropertyInfo in espressione di proprietà e utilizzarlo per invocare il metodo generico?

ho cercato di usare Expression.Property() per costruire espressione, ma sto ottenendo seguente errore quando uso questa espressione come propertyExpression parametro:

The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly.

Questo errore probabilmente si riferisce alla TProperty tipo di parametro che non so come specificare avendo solo PropertyInfo.

Sto facendo questo in relazione a: Use Entity Framework's StructuralTypeConfiguration.Ignore() to Ignore all properties but specified set.

UPDATE

codice che non funziona:

 var propertyInfo = typeof(Foo).GetProperties()[0]; 
     var expression = Expression.Default(typeof(Foo)); 
     var expressionProperty = Expression.Property(expression, propertyInfo); 
     Ignore(expressionProperty); 
+1

Dovresti mostrare il tuo codice che non funziona ... –

+0

@JonSkeet - aggiunto. – Pol

risposta

19
var entityType = propertyInfo.DeclaringType; 
var parameter = Expression.Parameter(entityType, "entity"); 
var property = Expression.Property(parameter, propertyInfo); 
var funcType = typeof(Func<,>).MakeGenericType(entityType, propertyInfo.PropertyType); 
var lambda = Expression.Lambda(funcType, property, parameter); 

structureConfiguration.GetType() 
    .GetMethod("Ignore") 
    .MakeGenericMethod(propertyInfo.PropertyType) 
    .Invoke(structureConfiguration, new[]{lambda}); 
+0

Provato, ma ottenendo 'Il tipo o il metodo ha 1 parametro/i generico/i, ma sono stati forniti 2 argomenti generici. Un argomento generico deve essere fornito per ogni parametro generico. Errore.StackTrace: a System.RuntimeType.SanityCheckGenericArguments (RuntimeType [] genericArguments, RuntimeType [] genericParamters) a System.Reflection.RuntimeMethodInfo.MakeGenericMethod (Tipo [] methodInstantiation) a Here_is_this_code (DbModelBuilder ModelBuilder) – Pol

+1

Quando ho detto '.MakeGenericMethod (...) 'Ho ottenuto che le operazioni tardive non possano essere eseguite su tipi o metodi per cui ContainsGenericParameters è vero. – Pol

+0

prova la variante corrente –

1

TProperty esiste solo nel C# codice sorgente di testo. Il compilatore lo risolve sempre in un tipo concreto. Se si dispone di un metodo

void Test<T>(T arg) 
{ 
} 

e chiamare in questo modo

Test("hello"); 
Test(3); 

Il compilatore genera il codice per due metodi!

void Test(string arg) 
{ 
} 

void Test(int arg) 
{ 
} 

Ciò significa che è necessario fornire tipi concreti per i parametri generici se si desidera avere un metodo invokable.

2

Le espressioni di proprietà richiedono che l'accesso alla proprietà sia su un oggetto specifico. Ci sono alcune opzioni che puoi prendere qui. In primo luogo, se questo viene fatto all'interno di uno dei tuoi oggetti entità, è possibile utilizzare un semplice ConstantExpression per costruire l'espressione di proprietà:

// Already have PropertyInfo in propInfo 
Expression.Property(Expression.Constant(this, this.GetType()), propInfo) 

Tuttavia, dal momento che è necessario un Expression<Func<TStructuralType, TProperty>>, allora sembra che si sta andando a devono costruire utilizzando un ParameterExpression:

ParameterExpression pe = Parameter.Expression(typeof(MyEntity), "eParam"); 
Expression propExp = Expression.Property(pe, propInfo); 

TUTTAVIA, ecco il kicker ... Questo è solo un MemberExpression. Per convertire nell'espressione necessaria, è necessario utilizzare Expression.Lambda per ottenere un'espressione Func <> del tipo necessario. Il problema? Non conosci il tipo di proprietà per definire i parametri generici dell'espressione lambda!

Expression<Func<MyEntity, ????>> eFunc = Expression.Lambda<Func<MyEntity, ????>>(propExp, pe); 

Questo è il punto cruciale del problema di farlo in questo modo. Questo non vuol dire che non si possa fare ... E 'solo che usare questo metodo IN QUESTO MODO non funzionerà. Dovrai utilizzare un po 'di runtime e l'enigma della digitazione statica (oltre a un uso giudizioso delle azioni anziché di Func) per far funzionare correttamente questo.

Problemi correlati