Extension method that works on IEnumerable<T> and IQueryable<T>? - c#

I want an extension method that works on both my List and IQueryable. The extension methods below accomplish this, but then if I add another identical extension method, but on a different totally unrelated type I get ambiguous call
compile errors. Why is that? Isn't the compiler smart enough to know which extension method works? I mean, only one of these calls is valid, why can't the compiler tell? Thanks a lot!
class ClassA
{
public bool IsActive{ get; set;}
}
class ClassB
{
public bool IsActive { get; set;}
}
// then here are my extensions
public static T IsActive<T>(this T enumerableOrQueryable, bool isActive)
where T : IEnumerable<ClassA>
{
return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive);
}
public static T IsActive<T>(this T enumerableOrQueryable, bool isActive)
where T : IEnumerable<ClassB>
{
return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive);
}

The overload rules don't take account of the constraints on methods that it's considering - it determines which overload is best and then validates that the constraints match.
The compiler is exactly following the rules of the C# specification.
Related blog posts:
Overloading and generic constraints (me)
Constraints are not part of the signature (Eric Lippert)
Evil code - overload resolution workaround (me - really nasty stuff, but fun)
EDIT: Note that using an "enumerableOrQueryable" is always going to convert your lambda expression to a delegate, not an expression tree. So if you wanted it to perform the logic differently for a database, you'd need a change anyway.
EDIT: Your idea also wouldn't work because you wouldn't get the same result type out anyway - if you call Where on a List<string>, the returned value isn't a List<string>.
What you can do is this, if you can introduce a new interface to be implemented by both ClassA and ClassB:
public static IQueryable<T> IsActive<T>(this IQueryable<T> source, bool isActive)
where T : ICanBeActive
{
// Lambda converted to an expression tree
return source.Where(x => x.IsActive == isActive);
}
public static IEnumerable<T> IsActive<T>(this IEnumerable<T> source,
bool isActive) where T : ICanBeActive
{
// Lambda converted to a delegate
return source.Where(x => x.IsActive == isActive);
}

The compiler cannot resolve ambiguity from the generic constraints. For your case, can't you just do something like this ?
public static IEnumerable<ClassA> IsActive(this IEnumerable<ClassA> enumerableOrQueryable, bool isActive)
{
return enumerableOrQueryable.Where(x => x.IsActive == isActive);
}

You can try something like this:
public interface IActivatable
{
bool IsActive { get; set; }
}
public class ClassA : IActivatable
{
public bool IsActive{ get; set;}
}
public class ClassB : IActivatable
{
public bool IsActive { get; set;}
}
public static class Ext
{
public static IEnumerable<T> IsActive<T>(this IEnumerable<T> collection, bool isActive) where T : IActivatable
{
return collection.Where(x => x.IsActive == isActive);
}
}

Related

one generic class create generic extension with expression<T,bool> method

My code is as follows:
public partial class WhereHelper<T1> { }
public static partial class WhereHelperExtension
{
public static T Where<T,T1>(this T t, Expression<Func<T1,bool>> where) where T : WhereHelper<T1>
{
//do something....
return t;
}
}
public class Test
{
public void Main()
{
WhereHelper<DateTime> dt = new WhereHelper<DateTime>();
dt.Where(t => t.Year == 2016);//this is error
dt.Where<WhereHelper<DateTime>, DateTime>(t => t.Year == 2016);//this is success
}
}
Extension method I want to be like this:
WhereHelper<DateTime> dt = new WhereHelper<DateTime>();
dt.Where(t => t.Year == 2016);//this is error
how to create generic extension with Expression method.
Visual Studio does not recognize the "Where" extension methods.
In C#, if you need to provide any generic argument, you must provide them all. where constraints do not provide hints to the type resolver, and so it's impossible to decide what T1 is.
Change your signature to the following:
public static WhereHelper<T> Where<T>(this WhereHelper<T> t, Expression<Func<T,bool>> where)
{
return t;
}
Here, we know exactly what T, purely from the first argument, and so we do not have to explicitly specific the arguments.

Any significant reason to avoid `as IQueryable`?

I have a library of model-to-viewmodel mapping extension methods. Supporting them is a base class with a few common methods, including Transform, below:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
var queryable = value as IQueryable<TOriginal> ?? value.AsQueryable();
return queryable.Select(Expression);
}
My question: is there any significant reason, besides a negligible performance hit, that I should avoid the as IQueryable cast above? For example, I could instead do the following:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IQueryable<TOriginal> value)
{
return value.Select(Expression);
}
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
... but I would prefer not to have to write the overloads in every one of my dependent classes. EDIT: To clarify, here is an example of what I'm seeking to avoid:
public static class TransformCompany
{
private static readonly TransformBase<Organization, CompanyHeader> header = new TransformPrecompiled<Organization, CompanyHeader>(
company => new CompanyHeader
{
Name = company.Name,
});
public static IQueryable<CompanyHeader> AsHeaders(this IQueryable<Organization> companies)
{
return header.Transform(companies);
}
// Note I have to include this capability in each of my dependent classes
// Worse is the possibility that someone may accidentally implement
// only IEnumerable for a future model transformation,
// causing a hidden data performance problem
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
I would say you do not need separate extensions for IEnumerable<T> and IQueryable<T> as IQueryable<T> inherits from IEnumerable<T>, and you also do not need to the cast.
Looking at referencesource, AsQueryable() actually does this check for you:
public static IQueryable<TElement> AsQueryable<TElement>(this IEnumerable<TElement> source)
{
if (source == null)
throw Error.ArgumentNull("source");
if (source is IQueryable<TElement>)
return (IQueryable<TElement>)source;
return new EnumerableQuery<TElement>(source);
}
Therefore the following should work for you with no performance hit:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
}
public static class TransformCompany
{
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
}
Queryable.AsQueryable Method (IEnumerable)
If the type of source implements IQueryable,
AsQueryable(IEnumerable) returns it directly. Otherwise, it returns an
IQueryable that executes queries by calling the equivalent query
operator methods in Enumerable instead of those in Queryable.
Instead of casting you simplify your Transform method to
return value.AsQueryable().Select(Expression);

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);
}
}

Creating generic Expression

I have a problem regarding generic expressions.
I have an Expression<Func<T, bool>> and I want to convert the Expression<Func<T, bool>> to Expression<Func<Y, bool>>. The object of class T has the same properties as the class Y.
Does anybody know how to solve this?
The "preferred" way to do this is use a Interface that contains the property you care about.
interface IMyProp
{
string SomeProp {get;}
}
class T : IMyProp
{
public string SomeProp
{
get
{
//Some complicated logic
}
}
}
class Y : IMyProp
{
public string SomeProp {get; set;}
}
The just code your expression to Expression<Func<IMyProp, bool>>
However it is understandable that you can not always do this, for situations like this you can use a library like AutoMapper
class T
{
public string SomeProp
{
get
{
//Some complicated logic
}
}
}
class Y
{
public string SomeProp {get; set;}
}
//Some initiation code somewhere else in your project
public static void InitializeMappings()
{
Mapper.CreateMap<T, Y>();
}
public static IQueryable<Y> FilterOnTAndMapToY(IQueryable<T> source, Expression<Func<T,bool>> filter)
{
return source.Where(filter).Project().To<Y>();
}
Now this does not exactly turn your Expression<Func<T, bool>> in to a to Expression<Func<Y, bool>> but it does let you use your T expression and use it to get a Y result after the filtering has been applied.
The way AutoMapper's Queryable Extensions work is the querys and casts to go from T to Y happen all server side when you are doing LinqToEntities. So you could even do
public static IQueryable<Y> MultiFilterCast(IQueryable<T> source, Expression<Func<T,bool>> tTypeFilter, Expression<Func<Y,bool>> yTypeFilter)
{
var filteredStage1 = source.Where(tTypeFilter);
var castToY = filteredStage1.Project().To<Y>();
var filteredStage2 = castToY.Where(yTypeFilter);
return filteredStage2;
}
both tTypeFilter and yTypeFilter will be applied server side before you get the result set.

Generic method how to return all of type T

say I have the following code:
public class Pond
{
public List<Frog> Frogs { get; set; }
public List<MudSkipper> MudSkippers { get; set; }
public List<Eel> Eels { get; set; }
}
public class Frog: IAquaticLife
{
}
public class MudSkipper: IAquaticLife
{
}
public class Eel: IAquaticLife
{
}
Now I want to write a generic method that will for a certain pond return the list of these types:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return Uow.GetByID<Pond>(pondId).Eels;
}
Ok, so what I have there will return all the eels in that pond. What I was wanting to do was to return all the T's.
so if I called GetByPond<MudSkipper>(1) that would return all the mudskippers.
Anyone know how to do this?
How about something like
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return from t in Uow.GetByID<Pond>(pondId).AquaticLife()
where (typeof(t) == typeof(T)) select t;
}
or simply (using the approach that #DStanley pointed out before changing his answer)
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return Uow.GetByID<Pond>(pondId).AquaticLife().OfType<T>();
}
That requires Uow.GetByID(int id) to return all types of creatures in the particular pond that implement IAquaticLife. The alternative, though, is that you hard-code knowledge of the various implementers of IAquaticLife into your generic method. That is not a good idea.
UPDATE
Currently a Pond has separate collections for Eels, Mudskippers, etc. That becomes fragile if you want to add more things that implement IAquaticLife as your code evolves because you have to change both Pond and the generic method above.
I suggest that instead of separate methods for each type of aquatic life, you instead have a single method that returns everything in the pond that implements IAquaticLife, e.g.
public class Pond
{
public IEnumerable<IAquaticLife> AquaticLife() { ... }
}
I have updated my code above with this assumption.
Anyone that has a Pond instance and wants to get, say, just the Eels can do this:
var eels = pond.AquaticLife().OfType<Eels>();
Try this:
return Uow.GetByID<Pond>(pondId).OfType<T>();
EDIT
Since you've got the collections in separate properties, you could use either a switch block to return the right property based on the type, or use reflection to get the property based on the type name.
A better design based on your requirement would be to have a private List<IAquaticLife> that would store all of the critters instead of separate properties, but I'll assume that you can't do that right now.
An example of the switch would be:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
switch(typeof(T))
{
case typeof(Eel):
return Uow.GetByID<Pond>(pondId).Eels;
//etc.
default:
throw new ApplicationException(string.Format("No property of type {0} found",typeof(T).Name));
}
}
public Pond GetByPond(int pondId)
{
return Uow.GetByID<Pond>(pondId);
}
If you want your Frogs, do:
var frogs = xxx.GetByPond(1).Frogs;
If you want your MudSkippers, do:
var mudSkippers = xxx.GetByPond(1).MudSkippers;
And so on.
If you can call GetByPond<Frog>(1), you can call GetByPond(1).Frogs.
If in any case you don't know the T, you'll need to create a collection of all of them and filter them by the type. This is also useful if you have intermediate subtype:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
var pond = Uow.GetByID<Pond>(pondId);
var life = pond.Frogs.Union(pond.Eels).Union(pond.MudSkippers);
return life.OfType<T>();
}
But you are concatenating the collections just to filter them.

Categories