C# Type Mirroring - c#

Is it possible in C# to have something I could call dynamic type mirroring, for lack of a better term?
Say, an application talks to a database that has multiple tables, each of which has an entity in the code of the usual sort:
public class SomeEntity
{
int ID { get; set; }
string Name { get; set; }
};
etc.
Now, is it possible to have a class that dynamically mirrors the types of these entities:
public class FilterType<T, U>
{
T Field1;
bool Apply<T>(T operand, T comparand);
};
such that T is dynamically int, for instance?
If I recall right, generics are compile-time determined, so this wouldn't be possible. Is there anything that could approximate this behaviour?
I need this to be able to filter fields in a table, and ideally I want this to be as generic as possible with minimal coupling. To add more substance, here's some code from my filter types:
public interface IFilter
{
string Representation { get; }
}
public interface IFilterBinary : IFilter
{
bool Apply<T>(T source, T operand1, T operand2) where T : IComparable;
}
public interface IFilterUnary : IFilter
{
bool Apply<T>(T source, T operand) where T : IComparable;
}
public class IsGreaterOrEqual : IFilterUnary
{
public string Representation { get; } = ">=";
public bool Apply<T>(T source, T operand) where T : IComparable
{
return source.CompareTo(operand) >= 0;
}
}
The problem with this is that when I try to use the filters, I hit a snag:
var property = typeof (User).GetProperties().Single(x => x.Name == rule.FieldName);
var fieldValue = property.GetValue(user);
var fieldType = property.PropertyType;
var value = Convert.ChangeType(fieldValue, fieldType); // Here the return type is `object`, so this line is useless.
Applying the filter filter.Apply(value, operand) fails because value is an object.
Thanks.

I think better for you using DynamicLinq lib.
As for your current approach, if you use reflection for getting value, just use it for calling function, like this:
var property = typeof (User).GetProperty(rule.FieldName);
var fieldValue = property.GetValue(user);
var fieldType = property.PropertyType;
var result = filter.GetType().GetMethod("Apply").MakeGenericMethod(fieldType).Invoke(filter, fieldValue, operand);
but anyway in this case result was boxed to object.

Related

Changing the return type of an expression<func<>>

Say I have an Expression<Func<T,object>> is it possible to dynamically change the return type based on a Type variable to be something like Expression<Func<T,int>>
I have the following class:
public class ImportCheck<T> {
public int id { get; set; }
public string Name { get; set; }
public Type Type { get; set; }
public bool Required { get; set; }
public int? MinLength { get; set; }
public int? MaxLength { get; set; }
public string Value { get; set; }
public Expression<Func<T, object>> AssociatedProperty { get; set; }
}
I have a List<ImportCheck<Contact>> which I loop through and for each one set a property on the Contact object (the properties are all different types). To enable me to set the property of nested objects I need the result type to be the same as the target type.
If all the properties of the contact were say int then what I have now would work fine it's the fact that I have a list of different types that is causing me the headache.
This is how I set a sub property:
private static Action<M, R> MakeSet<M, R>(Expression<Func<M, R>> fetcherExp) {
if (fetcherExp.Body.NodeType != ExpressionType.MemberAccess) {
throw new ArgumentException(
"This should be a member getter",
"fetcherExp");
}
// Input model
var model = fetcherExp.Parameters[0];
// Input value to set
var value = Expression.Variable(typeof(R), "v");
// Member access
var member = fetcherExp.Body;
// We turn the access into an assignation to the input value
var assignation = Expression.Assign(member, value);
// We wrap the action into a lambda expression with parameters
var assignLambda = Expression.Lambda<Action<M, R>>(assignation, model, value);
return assignLambda.Compile();
}
This is then called like MakeSet(member)(target,value) where member is the Expression<Func<T,object>> target is the object and value is the value to set the property to.
Please find the example below:
public class ReturnTypeVisitor<TSource, TReturnValue> : ExpressionVisitor{
protected override Expression VisitLambda<T>(Expression<T> node)
{
var delegateType = typeof(Func<,>).MakeGenericType(typeof(TSource), typeof(TReturnValue));
return Expression.Lambda(delegateType, Visit(node.Body), node.Parameters);
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.DeclaringType == typeof(TSource))
{
return Expression.Property(Visit(node.Expression), node.Member.Name);
}
return base.VisitMember(node);
}
}
Usage:
public class Foo{
public Bar Bar { get; set; }
}
public class Bar { }
Expression<Func<Foo, object>> expression = p => p.Bar;
Expression<Func<Foo, Bar>> stronglyTypedReturnValue = (Expression<Func<Foo, Bar>>)new ReturnTypeVisitor<Foo, Bar>().Visit(expression);
Sure; you can create a new expression tree with a cast from object to whatever type you want (no guarrantees the cast will hold, of course) - and you can use parts of the old expression tree (namely the entire lambda body) in your new expression tree.
However, even if you create such a thing, note that if you want to express the type of the expresion statically - e.g. Expression<Func<T,int>> you're going to need to know the type statically. Generics would work - but a runtime Type variable isn't.
There are several problems with your approach:
You assume that fetcherExp.Body is a member access, e.g. obj.TheProperty. However, if the expression is of type Expression<Func<T,object>> then any value-type property will be represented as a "Convert(obj.TheProperty)".
You assume there's a setter corresponding to the getter.
You assume that the Type property is correct.
I suggest you approach this problem differently. Instead of dealing with improperly typed Expression<Func<T,object>> objects and trying to generate setters (and getters?) from that, I suggest you start from an accurately typed Expression<Func<T,TProperty>> - or even just a PropertyInfo and generate typed getters and setters. Once you have a Func<T,TProperty> getter and an Action<T,TProperty> setter, you can easily wrap those to generate less specific actions and funcs:
public static Action<T,object> UntypeSetter<T,TProperty>(Action<T,TProperty> typedSetter) =>
(o, val) => typedSetter(o, (TProperty)val);
A similar approach is useful for getters (but this only matters for getters of value-type properties since covariance means that reference type getters can all be cast to Action<T,object>).
If you absolutely need maximal runtime performance, you can do exactly the same wrapping trick with Expression<...>s and inline the nested call to typedSetter, but note that you're not winning that much; the difference between one and two delegate calls is unlikely to matter for most applications.
TL;DR: Don't use Expression<Func<T,object>> as an intermediate representation of an untyped property; doing so throws away type information useful to creating getters/setters. Instead, use a typed expression Expression<Func<T,TProperty>> to easily generate untyped getters and setters, and pass those around as your intermediate representation.
Just use Expression.Convert on expression body:
public static class ExpressionHelper
{
public static Expression<Func<TSource, TConvertedResult>> ConvertResult<TSource, TResult, TConvertedResult>(Expression<Func<TSource, TResult>> expression)
{
return Expression.Lambda<Func<TSource, TConvertedResult>>(Expression.Convert(expression.Body, typeof(TConvertedResult)), expression.Parameters);
}
}
Tests:
[TestFixture]
public class ExpressionHelperTest
{
public class BaseClass
{
public BaseClass(bool boolean)
{
Boolean = boolean;
}
public bool Boolean { get; set; }
}
public class DerivedClass : BaseClass
{
public DerivedClass(bool boolean, int integer) : base(boolean)
{
Integer = integer;
}
public int Integer { get; set; }
}
[Test]
public void ConvertResult_Simple_Test()
{
Expression<Func<int, bool>> notNullExpression = i => i != 0;
Expression<Func<int, object>> notNullObjectResultExpression = ExpressionHelper.ConvertResult<int, bool, object>(notNullExpression);
Func<int, bool> notNull = notNullExpression.Compile();
Func<int, object> notNullObjectResult = notNullObjectResultExpression.Compile();
Assert.True(notNull(1));
Assert.False(notNull(0));
Assert.AreEqual(true, notNullObjectResult(1));
Assert.AreEqual(false, notNullObjectResult(0));
Assert.Pass();
}
[Test]
public void ConvertResult_Inheritance_Test()
{
Expression<Func<(bool boolean, int integer), DerivedClass>> derivedClassExpression = x => new DerivedClass(x.boolean, x.integer);
Expression<Func<(bool boolean, int integer), BaseClass>> baseClassExpression = ExpressionHelper.ConvertResult<(bool boolean, int integer), DerivedClass, BaseClass>(derivedClassExpression);
Expression<Func<(bool boolean, int integer), DerivedClass>> derivedClassFromBaseClassExpression = ExpressionHelper.ConvertResult<(bool boolean, int integer), BaseClass, DerivedClass>(baseClassExpression);
Func<(bool boolean, int integer), DerivedClass> derivedClass = derivedClassExpression.Compile();
Func<(bool boolean, int integer), BaseClass> baseClass = baseClassExpression.Compile();
Func<(bool boolean, int integer), DerivedClass> derivedClassFromBaseClass = derivedClassFromBaseClassExpression.Compile();
(bool boolean, int integer) trueAndOne = (true, 1);
(bool boolean, int integer) falseAndZero = (false, 0);
Assert.True(derivedClass(trueAndOne).Boolean);
Assert.False(derivedClass(falseAndZero).Boolean);
Assert.AreEqual(1, derivedClass(trueAndOne).Integer);
Assert.AreEqual(0, derivedClass(falseAndZero).Integer);
Assert.True(baseClass(trueAndOne).Boolean);
Assert.False(baseClass(falseAndZero).Boolean);
Assert.True(derivedClassFromBaseClass(trueAndOne).Boolean);
Assert.False(derivedClassFromBaseClass(falseAndZero).Boolean);
Assert.AreEqual(1, derivedClassFromBaseClass(trueAndOne).Integer);
Assert.AreEqual(0, derivedClassFromBaseClass(falseAndZero).Integer);
Assert.Pass();
}
}
Here is a simple way to change the return value of an Expression<Func<>> for a very simple case:
Expression<Func<int, bool>> x = t => t > 1;
var prmi = Expression.Parameter(typeof(int), "i");
var lambda = Expression.Lambda<Func<int, int>>(Expression.Convert(Expression.Invoke(x,prmi), typeof(int)),prmi);
var i = lambda.Compile().Invoke(2); //returns an int

Query over interface properties using EntityFramework and LinqKit

I'm using EntityFramework and LinqKit to build expressions trees which get translated into SQL. Also we use the specification pattern to organize our queries.
There is a need in almost all of our domain objects to execute a query by description, but in some of those classes the property is called "Name", in others "Description", etc.
So initially was defined a interface as follow:
public interface IDescritible
{
string Description { get; }
}
The problem appeared when I tried to use it implemented explicitly in a class and made a generic query upon that:
public class Foo : IDescritible
{
public string Name { get; set; }
string IDescritible.Description
{
get { return this.Name; }
}
}
public class DescriptionMatch<T> : AbstractSpecification<T>
where T : IDescritible
{
public string Query { get; set; }
public DescriptionMatch(string query)
{
this.Query = query;
}
public override Expression<Func<T, bool>> IsSatisfiedBy()
{
return x => x.Description.Contains(Query);
}
}
When run, the EntityFramework is unable to translate the property get (a method call) into a SQL expression.
Then I tried to define a Expression in the class as follows:
public interface IDescritible<T> where T: IDescritible<T>
{
Expression<Func<T, string>> DescriptionExpression { get; }
}
public class Foo : IDescritible<Foo>
{
public string Name { get; set; }
public Expression<Func<Foo, string>> DescriptionExpression
{
get { return x => x.Name; }
}
}
public class DescriptionMatch<T> : AbstractSpecification<T> where T : IDescritible<T>
{
public string Query { get; set; }
public DescriptionMatch(string query)
{
this.Query = query;
}
public override Expression<Func<T, bool>> IsSatisfiedBy()
{
Expression<Func<T, bool>> combinedExpression = x => x.DescriptionExpression.Invoke(x).Contains(this.Query);
return combinedExpression.Expand();
}
}
But when it executes the .Expand() a exception is thrown: Unable to cast object of type 'System.Linq.Expressions.PropertyExpression' to type 'System.Linq.Expressions.LambdaExpression'.
Then I found out that LinqKit only support expanding local defined expressions (as stated on this question) and that there are some unoficial code write to solve those issues (answers on this question).
But when I modified the LinqKit library to try either one of the proposed solutions in second question it started to throw: variable 'x' of type 'Foo' referenced from scope '', but it is not defined.
Maybe that was caused by the fact that I don't have a instance of Foo yet? Only got the generic type parameter, and that's why I can't define my expression on a local variable. Maybe there is a way to define as a static expression somehow "attached" into class? But then I would not be able to use it in a generic query, there will be no interface...
There is a way to modify LinqKit so I can build expressions defined on a explicit implementation of a interface? Or there is another way to make a generic query upon properties explicitly implemented? Or any other solution or things to look into?
There is no need to use neither LinqKit or specification pattern for that, but EntityFramework is mandatory, what is important is to have a interface/any other way that support "pointing out" which property is the description property and make a generic Expression upon that.
Thank you in advance!
The easiest way to do it is to make the following change
public class DescriptionMatch<T> : AbstractSpecification<T> where T : IDescritible<T>, new()
Then you can get an instance by simply newing up a T (which EF), using the expression and otherwise discarding the object
public interface IDescritible<T> where T : IDescritible<T>
{
Expression<Func<T, string>> DescriptionExpression { get; }
}
public class Foo : IDescritible<Foo>
{
public string Name { get; set; }
public Expression<Func<Foo, string>> DescriptionExpression
{
get { return x => x.Name; }
}
}
public abstract class AbstractSpecification<T>
{
public abstract Expression<Func<T, bool>> IsSatisfiedBy();
}
public class DescriptionMatch<T> : AbstractSpecification<T>
where T : IDescritible<T>, new()
{
public string Query { get; set; }
public DescriptionMatch(string query)
{
this.Query = query;
}
public override Expression<Func<T, bool>> IsSatisfiedBy()
{
Expression<Func<T, string>> lambda = new T().DescriptionExpression;
return Expression.Lambda<Func<T, bool>>(
Expression.Call(
lambda.Body,
"Contains",
Type.EmptyTypes,
Expression.Constant(
this.Query,
typeof(string)
)
),
lambda.Parameters
);
}
}
public class ExpressionReplacer : ExpressionVisitor
{
private readonly Expression _toBeReplaced;
private readonly Expression _replacement;
public ExpressionReplacer(Expression toBeReplaced, Expression replacement)
{
if (toBeReplaced.Type != replacement.Type)
{
throw new ArgumentException();
}
this._toBeReplaced = toBeReplaced;
this._replacement = replacement;
}
public override Expression Visit(Expression node)
{
return Object.ReferenceEquals(node, this._toBeReplaced) ? this._replacement : base.Visit(node);
}
}

Filtering on template list with property name as string

Hi I have to apply filter on generic class. The sample class is as follows
public class Sample<T>
{
List<T> sourceList = new List<T>();
public void applyFilter(string propertyName , EnumOperator operator , object value)
{
}
}
Here I want to implement filter using linq or dynamic linq but am not getting any positive direction to implement this functionality.
Please give me some positive direction so that I can implement this functionality.
Thanks.
I would recommend returning an filtered list instead of modifying the source, and also the string "operator" is a C# keyword, so the signature of the method could be:
public List<T> ApplyFilter(string propertyName, EnumOperator operatorType, object value)
{
....
}
where I assume that the EnumOperator is an enum with values like this:
public enum EnumOperator
{
Equal,
NotEqual,
Bigger,
Smaller
}
and that you have some way to check if for an operator a value passes or fails the test, something along the lines of:
public static class OperatorEvaluator
{
public static bool Evaluate(EnumOperator operatorType, object first, object second)
{
...
}
}
Given that, you can do something like:
public List<T> ApplyFilter(string propertyName , EnumOperator operatorType, object value)
{
PropertyInfo pi = typeof(T).GetProperty(propertyName);
List<T> result = sourceList.Where(item => {
var propValue = pi.GetValue(item, null);
return OperatorEvaluator.Evaluate(operatorType, propValue, value);
}).ToList();
return result;
}
That said, you can always use LINQ's methods to filter almost anything without resorting to reflection.
To query with dynamic expression (as string), you can use Dynamic LINQ by Scott Gu of Microsoft.
Samples
It supports following operations
1. Select
2. Where
3. OrderBy
4. Skip
5. Take
6. GroupBy
All above operations take string as parameter.
It also has small expression language (to build selectors/predicates/etc) which is very easy to use.
Example:
var query =
db.Customers.
Where("City = #0 and Orders.Count >= #1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");
Here I give you a sample example how to implement filtering using LINQ on List<T> items..
public class clsCountry
{
public string _CountryCode;
public string _CountryName;
//
public clsCountry(string strCode, string strName)
{
this._CountryCode = strCode;
this._CountryName = strName;
}
//
public string CountryCode
{
get {return _CountryCode;}
set {_CountryCode = value;}
}
//
public string CountryName
{
get { return _CountryName; }
set { _CountryName = value; }
}
}
Now, lets create a list of objects based on class clsCountry and store them in a List<T> object.
List<clsCountry> lstCountry = new List<clsCountry>();
lstCountry.Add(new clsCountry("USA", "United States"));
lstCountry.Add(new clsCountry("UK", "United Kingdom"));
lstCountry.Add(new clsCountry("IND", "India"));
Next, we shall bind the List<T> object lstCountry to a DropDownList control named drpCountry as like as:
drpCountry.DataSource = lstCountry;
drpCountry.DataValueField = "CountryCode";
drpCountry.DataTextField = "CountryName";
drpCountry.DataBind();
Now, use LINQ to filter data from the lstCountry object and bind the filtered list to the dropdown control drpCountry.
var filteredCountries = from c in lstCountry
where c.CountryName.StartsWith("U")
select c;
drpCountry.DataSource = filteredCountries;
drpCountry.DataValueField = "CountryCode";
drpCountry.DataTextField = "CountryName";
drpCountry.DataBind();
Now the dropdown control will have only 2 items
United States
United Kingdom
Now apply those techniques on your case..
You can use Reflection for retrieving the property value and you can use a simple switch statement upon the operator to perform the filtering:
public IEnumerable<T> ApplyFilter(string propertyName, EnumOperator op, object value)
{
foreach (T item in sourceList)
{
object propertyValue = GetPropertyValue(item, propertyName);
if (ApplyOperator(item, propertyValue, op, value)
{
yield return item;
}
}
}
private object GetPropertyValue(object item, string propertyName)
{
PropertyInfo property = item.GetType().GetProperty(propertyName);
//TODO handle null
return property.GetValue();
}
private bool ApplyOperator(object propertyValue, EnumOperator op, object value)
{
switch (op)
{
case EnumOperator.Equals:
return propertyValue.Equals(value);
//TODO other operators
default:
throw new UnsupportedEnumException(op);
}
}
(An optimization would be to look up the PropertyInfo once outside of the loop.)

Generic constraints with C# Expression<TDelegate> - Cannot implicitly convert Type

I've started using C# Expression constructs, and I've got a question about how generics are applied in the following situation:
Consider I have a type MyObject which is a base class for many different types. Inside this class I have the following code:
// This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects
public Expression<Func<MyObject, string, bool>> StringIndexExpression { get; private set;}
// I use this method in Set StringIndexExpression and T is a subtype of MyObject
protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson) where T : MyObject
{
StringIndexExpression = expression;
}
This is how I use DefineStringIndexer:
public class MyBusinessObject : MyObject
{
public string Name { get; set; }
public MyBusinessObject()
{
Name = "Test";
DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value);
}
}
However in the assignment inside DefineStringIndexer I get the compile error:
Cannot implicitly convert type
System.Linq.Expression.Expression< MyObject, string, bool > to
System.Linq.Expression.Expression < MyBusinessObject, string, bool >>
Can I use Generics with C# Expressions in this situation? I want to use T in DefineStringIndexer so I can avoid casting MyObject inside the lambda.
The assignment will not work, because the Func<MyBusinessObject,string,bool> type is not assignment-compatible with Func<MyObject,string,bool>. However, the parameters of the two functors are compatible, so you can add a wrapper to make it work:
protected void DefineStringIndexer<T>(Func<T,string,bool> expresson) where T : MyObject {
StringIndexExpression = (t,s) => expression(t, s);
}
Would this work better for you?
Edit: Added <T> to constraint - think you will need that :)
class MyObject<T>
{
// This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects
public Expression<Func<T, string, bool>> StringIndexExpression { get; private set;}
// I use this method in Set StringIndexExpression and T is a subtype of MyObject
protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson)
where T : MyObject<T> // Think you need this constraint to also have the generic param
{
StringIndexExpression = expression;
}
}
then:
public class MyBusinessObject : MyObject<MyBusinessObject>
{
public string Name { get; set; }
public MyBusinessObject()
{
Name = "Test";
DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value);
}
}

How to make IList compatible to IEnumerable during lambda expression?

I'm trying to convert this:
ISession.Query<Question>()
.Where(x => x.QuestionId == q.QuestionId)
.FetchMany(x => x.Answers)
.ToFuture();
To reflection type:
IQueryable<Question> query = ISession.Query<Question>().Where(string.Format("{0} = #0", "QuestionId"), q.QuestionId);
Type emType = typeof(NHibernate.Linq.EagerFetchingExtensionMethods);
MethodInfo mi = emType.GetMethod("FetchMany");
ParameterExpression paramEx = Expression.Parameter(typeof(Question), "x");
MemberExpression me = Expression.Property(paramEx, "Answers");
LambdaExpression lambdaEx = Expression.Lambda (me, paramEx);
// runtime error here
mi.MakeGenericMethod(typeof(Question), typeof(Answer)).Invoke(emType, new object[] { query, lambdaEx });
The runtime error:
System.ArgumentException: Object of type
'System.Linq.Expressions.Expression`1
[System.Func`2[TestXXX.TheModels.Question,
System.Collections.Generic.IList`1[TestXXX.TheModels.Answer]]]'
cannot be converted to type
'System.Linq.Expressions.Expression`1
[System.Func`2[TestXXX.TheModels.Question,
System.Collections.Generic.IEnumerable`1[TestXXX.TheModels.Answer]]]'.
POCO sample:
The Answers in Question is an IList, please don't advise to change IList to IEnumerable ;-)
public class Question
{
public virtual int QuestionId { get; set; }
public virtual string QuestionText { get; set; }
public virtual IList<Answer> Answers { get; set; }
}
Here's the method signature of FetchMany:
namespace NHibernate.Linq
{
public static class EagerFetchingExtensionMethods
{
public static INhFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector);
}
}
What should be done so it's possible to pass an IList to NHibernate's FetchMany's IEnumerable during reflection?
Note: can pass IList to IEnumerable if we are not using reflection
Change this
MemberExpression me = Expression.Property(paramEx, "Answers");
to this:
Expression me = Expression.Convert(Expression.Property(paramEx, "Answers"), typeof(IEnumerable<Answer>));
The reason for the error you are receiving is that the delegate types of your lambda do not agree. We need to make the types compatible by artificially treating an IList<T> as an IEnumerable<T>.
This is kind of a hack as any proponent of dynamic languages would say ;-) Anyway, it reliably works.

Categories