2012-03-08 11 views
11

Làm thế nào để chuyển đổi PropertyInfo thành biểu thức thuộc tính có thể được sử dụng để gọi phương thức StructuralTypeConfiguration<TStructuralType>.Ignore<TProperty>(Expression<Func<TStructuralType, TProperty>> propertyExpression)?Làm thế nào để chuyển đổi PropertyInfo thành biểu thức thuộc tính và sử dụng nó để gọi phương thức chung?

Tôi cố gắng để sử dụng Expression.Property() để xây dựng biểu nhưng tôi nhận được lỗi sau khi tôi sử dụng biểu thức này như propertyExpression tham số:

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

Lỗi này có thể đề cập đến TProperty loại tham số mà tôi không biết cách chỉ định chỉ có PropertyInfo.

Tôi đang thực hiện việc này liên quan đến: Use Entity Framework's StructuralTypeConfiguration.Ignore() to Ignore all properties but specified set.

CẬP NHẬT

Mã mà không hoạt động:

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

Bạn nên hiển thị mã không hoạt động ... –

+0

@JonSkeet - đã thêm. – Pol

Trả lời

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

Đã thử, nhưng nhận 'Kiểu hoặc phương thức có 1 tham số chung, nhưng 2 đối số chung đã được cung cấp. Đối số chung phải được cung cấp cho mỗi lỗi parameter.' chung.StackTrace: tại System.RuntimeType.SanityCheckGenericArguments (RuntimeType [] genericArguments, RuntimeType [] genericParamters) tại System.Reflection.RuntimeMethodInfo.MakeGenericMethod (Gõ [] methodInstantiation) tại Here_is_this_code (DbModelBuilder modelBuilder) – Pol

+1

Khi tôi nhận xét '.MakeGenericMethod (...) 'Tôi nhận' Các hoạt động bị ràng buộc trễ không thể được thực hiện trên các kiểu hoặc phương thức mà ContainsGenericParameters là đúng.'. – Pol

+0

thử biến thể hiện tại –

1

TProperty chỉ tồn tại trong C# mã nguồn văn bản. Trình biên dịch luôn giải quyết nó thành một loại cụ thể. Nếu bạn có một phương pháp

void Test<T>(T arg) 
{ 
} 

và gọi nó như thế này

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

Trình biên dịch tạo ra mã cho hai phương pháp!

void Test(string arg) 
{ 
} 

void Test(int arg) 
{ 
} 

Điều này có nghĩa là bạn phải cung cấp các loại cụ thể cho các thông số chung của mình nếu bạn muốn có phương pháp không thể invokable.

2

Biểu thức thuộc tính yêu cầu quyền truy cập thuộc tính phải nằm trên một đối tượng cụ thể. Có một vài lựa chọn bạn có thể thực hiện ở đây. Thứ nhất, nếu điều này đang được thực hiện trong vòng một của các đối tượng thực thể, bạn có thể sử dụng đơn giản một ConstantExpression để xây dựng biểu thức bất động sản:

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

Tuy nhiên, kể từ khi bạn cần một Expression<Func<TStructuralType, TProperty>>, sau đó nó có vẻ như bạn đang đi tới phải xây dựng nó sử dụng một ParameterExpression:

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

TUY NHIÊN, đây là kicker ... đây chỉ là một MemberExpression. Để chuyển đổi thành biểu thức bạn cần, bạn cần sử dụng Expression.Lambda để nhận biểu thức Func <> của loại bạn cần. Vấn đề? Bạn không biết loại thuộc tính để xác định các tham số chung của biểu thức lambda!

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

Đây là mấu chốt của sự cố khi thực hiện theo cách này. Đó không phải là để nói rằng nó không thể được thực hiện ... Nó chỉ là bằng cách sử dụng phương pháp này TRONG CÁCH NÀY sẽ không hoạt động. Bạn sẽ phải sử dụng thời gian chạy bit và mẹo đánh máy tĩnh (cũng như sử dụng Hành động khôn ngoan thay vì Func) để làm việc này hoạt động chính xác.