I'd like to copy an object into a mock of the same Interface. The goal is, to do it dynamic. But it seems, that there is no way to convert a dynamic delegate into a function.
public static T GetCopiedMock<T>(T toCopy, T mockObject) where T : class
{
IEnumerable<PropertyInfo> properties = GetPropertyInfos(toCopy, typeof(T));
foreach (var property in properties)
{
var parameter = Expression.Parameter(typeof(T));
var result = Expression.Property(parameter, property);
var lamda = Expression.Lambda(result, parameter);
var compilat = lamda.Compile();
var funcType = typeof(Func<,>).MakeGenericType(typeof(T), property.PropertyType);
//Here is my problem
mockObject.Expect(new Func<T, property.PropertyType>(compilat));
}
return mockObject;
}
I know its not possible directly since propertytype is at runtime but is there is any workaround?
By the way, this is my first post. So if you see something terrible which i have to do better, tell me!
Related
I have a class Person
class Person
{
string Name;
int Age;
DateTime BirthDate;
}
I am trying to create an Expression to order an IQueryable<Person> by a given property name.
public IQueryable<Person> Order(IQueryable<Person> input, string sortColumnName)
{
Type type = typeof(Person);
PropertyInfo propertyInfo = type.GetProperty(sortColumnName);
Type pType = prop.Type;
ParameterExpression param = Expression.Parameter(type, "y");
Expression prop = param;
prop = Expression.Property(prop, propertyInfo);
// I want to achieve..
// var orderExpression = Expression.Lambda<Func<Person, "pType">>(prop, param);
// In order to do something like the above statement,
// I have to create a nested generic type of `Func<Person, "pType">`
Type e1 = typeof(Expression<>);
Type[] typeArgs = {typeof( Func <Person, pType>)};
Type orderType = e1.MakeGenericType(typeArgs);
// Need some help of how to create and use this Generic ""orderType"".
// ....
// Ultimately, it will by used somewhat like ...
//
// var orderExpression = Expression.Lambda<"orderType">(prop, param);
return input.OrderBy(orderExpression);
}
I am really confused by this inconsistent behavior of Expression trees.
In my project, I have an ""IQueryable<Person>"".Where(w1) that can easily take in an Expression w1.
I am simply trying to do the same by creating an ""IQueryable<Person>"".OrderBy(o1),
to successfully consume an Expression o1.
I would prefer to keep everything as IQueryable<>, instead of having to convert back and forth to IEnumerable<>.
Any help would be appreciated!
I'll left common solution. Expression tree is a nightmare only from start.
public IQueryable<T> Order(this IQueryable<T> input, string sortColumnName)
{
Type type = typeof(T);
var propertyInfo = type.GetProperty(sortColumnName);
if (propertyInfo == null)
throw new InvalidOperationException();
var param = Expression.Parameter(type, "y");
var orderLambda = Expression.Lambda(
Expression.MakeMemberAccess(param, propertyInfo),
param);
var queryExpr = Expression.Call(
typeof(Queryable),
"OrderBy",
new Type[] {
input.ElementType,
propertyInfo.PropertyType },
input.Expression,
orderLambda);
return input.Provider.CreateQuery<T>(queryExpr);
}
Note, that I can make small mistake because just writing from memory.
I want to get the Get Acessor of a Property (PropertyInfo) and compile it to a Func<object,object>. The declaring type is only known at runtime.
My current code is:
public Func<Object, Object> CompilePropGetter(PropertyInfo info)
{
MethodInfo getter = info.GetGetMethod();
ParameterExpression instance = Expression.Parameter(info.DeclaringType, info.DeclaringType.Name);
MethodCallExpression setterCall = Expression.Call(instance, getter);
Expression getvalueExp = Expression.Lambda(setterCall, instance);
Expression<Func<object, object>> GetPropertyValue = (Expression<Func<object, object>>)getvalueExp;
return GetPropertyValue.Compile();
}
Unfortunately, I have to put <Object,Object> as generic parameters, because sometimes I will get the properties of a Type, like typeof(T).GetProperties()[0].GetProperties(), where the first GetProperties()[] returns a custom-type object, and I have to reflect it.
When I run the code above, I get this error:
Unable to cast object of type 'System.Linq.Expressions.Expression`1[System.Func`2[**CustomType**,**OtherCustomType**]]' to type 'System.Linq.Expressions.Expression`1[System.Func`2[System.Object,System.Object]]'.
So, what can I do to return a Func<Object,Object>?
You can add casts to the expected type and from the return type using Expression.Convert:
public static Func<Object, Object> CompilePropGetter(PropertyInfo info)
{
ParameterExpression instance = Expression.Parameter(typeof(object));
var propExpr = Expression.Property(Expression.Convert(instance, info.DeclaringType), info);
var castExpr = Expression.Convert(propExpr, typeof(object));
var body = Expression.Lambda<Func<object, object>>(castExpr, instance);
return body.Compile();
}
I'm using simplemvvmtoolkit for validation (INotifyDataErrorInfo). Instead of me repeating my self over and over for each property within the view model, Id like to use reflection to get all the properties and validate them, I can't seem to figure out what to pass in the validateProperty method though.
private void ValidateInput()
{
var unitProperties = this.GetType().GetProperties()
.Where(x => x.CanRead);
foreach (var prop in unitProperties)
ValidateProperty(prop, prop.GetValue(this, null)); //????
//? ^ get errors here
}
ValidateProperty takes in:
protected virtual void ValidateProperty<TResult>(Expression<Func<TViewModel, TResult>> property, object value);
The problem is Expression<Func<TViewModel, TResult>> has absolutely no relation to PropertyInfo (the type returned by GetProperties). You'll also run into problems because the type of the result is not known at compile time.
The easiest solution would be to change ValidateProperty to accept a PropertyInfo:
protected virtual void ValidateProperty(PropertyInfo property, object value);
You could also convert the PropertyInfo to an Expression, but that's a bit more difficult:
var method = this.GetType().GetMethod("ValidateProperty");
foreach (var prop in unitProperties)
{
var parameter = Expression.Parameter(this.GetType(), "_");
var property = Expression.Property(parameter, prop);
var lambda = Expression.Lambda(property, parameter);
var genericMethod = method.MakeGenericMethod(prop.PropertyType);
genericMethod.Invoke(this, new object[] { lambda, prop.GetValue(this, null) });
}
What I want to do is take any class type and create a list of 'get' accessors to all of the properties in the object graph.
The exact format, order, etc of the collection doesn't matter, I just don't quite know how to start off identifying and creating accessors to all of the properties. It might take the form of something like this:
public static List<Func<T,object>> CreateAccessors<T>()
{
Type t = typeof(T);
// Identify all properties and properties of properties (etc.) of T
// Return list of lambda functions to access each one given an instance of T
}
public void MyTest()
{
MyClass object1;
var accessors = CreateAccessors<MyClass>();
var myVal1 = accessors[0](object1);
var myVal2 = accessors[1](object1);
// myVal1 might now contain the value of object1.Property1
// myVal2 might now contain the value of object1.Property4.ThirdValue.Alpha
}
You can use reflection to extract the properties and expression-trees to help build the delegates targeting the property getters:
// Start with all public instance properties of type
var accessors = from property in type.GetProperties
(BindingFlags.Instance | BindingFlags.Public)
// Property must be readable
where property.CanRead
//Assemble expression tree of the form:
// foo => (object) foo.Property
// foo
let parameter = Expression.Parameter(type, "foo")
// foo.Property
let propertyEx = Expression.Property(parameter, property)
// (object)foo.Property - We need this conversion
// because the property may be a value-type.
let body = Expression.Convert(propertyEx, typeof(object))
// foo => (object) foo.Property
let expr = Expression.Lambda<Func<T,object>>(body, parameter)
// Compile tree to Func<T,object> delegate
select expr.Compile();
return accessors.ToList();
Note that although Delegate.CreateDelegate seems like an obvious choice, you will have some problems boxing value-type properties. Expression-trees dodge this problem elegantly.
Note that you'll need some more work to be able to get "nested" properties out too, but hopefully I've given ypu enough to get you started (hint: recurse). One final pointer with that: watch out for cycles in the object graph!
public static List<Func<T, object>> CreateAccessors<T>()
{
var accessors = new List<Func<T, object>>();
Type t = typeof(T);
foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
if (prop.CanRead) {
var p = prop;
accessors.Add(x => p.GetValue(x, null));
}
}
return accessors;
}
EDIT:
Here is a variant which returns compiled expressions and should be much faster than the previous one using reflection
public static List<Func<T, object>> CreateAccessorsCompiled<T>()
{
var accessors = new List<Func<T, object>>();
Type t = typeof(T);
foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
if (prop.CanRead) {
ParameterExpression lambdaParam = Expression.Parameter(t, "instance");
Expression bodyExpression;
MemberExpression memberAccessExpression = Expression.MakeMemberAccess(Expression.Convert(lambdaParam, t), prop);
if (prop.PropertyType == typeof(object)) { // Create lambda expression: (instance) => ((T)instance).Member
bodyExpression = memberAccessExpression;
} else { // Create lambda expression: (instance) => (object)((T)instance).Member
bodyExpression = Expression.Convert(memberAccessExpression, typeof(object));
}
var lambda = Expression.Lambda<Func<T, object>>(bodyExpression, lambdaParam);
accessors.Add(lambda.Compile());
}
}
return accessors;
}
I'd like to "wrap" the getter function for a specific property that is part of a specific type.
I have an abstract class, defined like following:
public abstract class MyAbstractClass<T> where T : MyType
{
// ...
}
Well, suppose I've a concrete class like the following one:
public abstract class MyConcreteClass : MyAbstractClass<MyConcreteType>
{
// ...
}
And now, the helper method that should return a wrapper for the getter method:
private Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
{
var instanceType = Expression.Parameter(property.DeclaringType, "i");
// Taking getter's "body".
var getterBody = Expression.Property(instanceType, property);
// Cast to a generic Object.
var body = Expression.TypeAs(getterBody, typeof(Object));
// Build the expression.
var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(body, instanceType);
return exp.Compile();
}
Just like expected, I get the following exception:
ParameterExpression of type 'MyConcreteClass' cannot be used for
delegate parameter of type 'MyAbstractClass<MyConcreteType>'.
Is there a way to "force" this kind of casting? Thanks in advance.
If I understand your question correctly, you want to create a lambda expression like this:
Func<MyAbstractClass<T>, Object> f = i => ((MyConcreteClass)i).SomeProperty;
Except you want to provide which property is SomeProperty as a parameter. Well, if you want to build that expression programmatically, you have to do exactly the same: have expression parameter i (of type MyAbstractClass<T>), cast it to MyConcreteClass and then access property SomeProperty of that.
public Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
{
var parameter = Expression.Parameter(typeof(MyAbstractClass<T>), "i");
var cast = Expression.TypeAs(parameter, property.DeclaringType);
var getterBody = Expression.Property(cast, property);
var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(
getterBody, parameter);
return exp.Compile();
}
Having said that, I have absolutely no idea why would you want to do that, so you better be really sure this is what you want to do and that there isn't any better way of doing what you actually want to do.
Shouldn't you be building the instance type from the generic type?
var genericType = typeof(MyAbstractClass<>).MakeGenericType(property.DeclaringType);
var instanceType = Expression.Parameter(genericType , "i");