The difference in the expression <Func <T, bool >>
Just quick and short, this time. Func<T,TResult> contravariant ( EDIT : parameter of type T is). Now I am not working with Func<T,TResult>, but rather with, Expression<Func<T,TResult>>and it seems to have reached a dead end. UPDATE - SAMPLE FULL CODE:
public interface IColoredObject
{
string Color { get; }
}
public class Item : IColoredObject
{
public string Color { get; set; }
public double Price { get; set; }
}
public partial class MainWindow : Window
{
private IList<Item> _items;
public IList<Item> Items
{
get
{
if (_items == null)
{
_items = new List<Item>();
_items.Add(new Item() { Color = "black" });
_items.Add(new Item() { Color = "blue" });
_items.Add(new Item() { Color = "red" });
}
return _items;
}
}
public MainWindow()
{
InitializeComponent();
Expression<Func<IColoredObject, bool>> filter = x => x.Color == "black";
Item i = Get(filter);
}
public Item Get(Expression<Func<Item, bool>> filter)
{
return Items.AsQueryable().Where(filter).FirstOrDefault();
}
}
The call is made using the argument Expression<Func<IColoredObject, bool>>as an argument and should, if I did not understand the contravariance incorrectly, work because it is IColoredObjectless inferred that Item.
What I get is an exception conversion saying something like
can't convert
System.Linq.Expressions.Expression`1[System.Func`2[MyNs.IColoredObject,System.Boolean]]
For
System.Linq.Expressions.Expression`1[System.Func`2[MyNs.Item,System.Boolean]]
Is there a way to fix this and make it work?
EDIT:
, , . . , , MSDN Func<T, TRes>:
public Item GetFunc(Func<Item, bool> filter)
{
return Items.AsQueryable().Where(filter).FirstOrDefault();
}
MS, , :
Func<IColoredObject, bool> filterFunc = x => x.Color == "black";
GetFunc(filterFunc);
, Func<T, TRes>, Expression<Func<T, TRes>>...
...
, , . , Get NHibernate . , , NHibernate , . , , , , .
Expression<TDelegate> - , . Delegate Expression<Delegate>. Item Func<IColoredObject, bool> , , Func<IColoredObject, bool> Func<Item, bool>, Expression<Func<Item, bool>> , , Item bool. , Item, , , IColoredObject.
, IColoredObject Expression<Func<IColoredObject, bool>> Item, ExpressionVisitor. , (.. ). , , , .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
interface IGizmo
{
bool Frobnicate();
}
class Gizmo : IGizmo
{
public bool Frobnicate()
{
Console.WriteLine("Gizmo was frobnicated!");
return true;
}
}
public sealed class DelegateConversionVisitor : ExpressionVisitor
{
IDictionary<ParameterExpression, ParameterExpression> parametersMap;
public static Expression<Func<T2, TResult>> Convert<T1, T2, TResult>(Expression<Func<T1, TResult>> expr)
{
var parametersMap = expr.Parameters
.Where(pe => pe.Type == typeof(T1))
.ToDictionary(pe => pe, pe => Expression.Parameter(typeof(T2)));
var visitor = new DelegateConversionVisitor(parametersMap);
var newBody = visitor.Visit(expr.Body);
var parameters = expr.Parameters.Select(visitor.MapParameter);
return Expression.Lambda<Func<T2, TResult>>(newBody, parameters);
}
public DelegateConversionVisitor(IDictionary<ParameterExpression, ParameterExpression> parametersMap)
{
this.parametersMap = parametersMap;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return base.VisitParameter(this.MapParameter(node));
}
private ParameterExpression MapParameter(ParameterExpression source)
{
var target = source;
this.parametersMap.TryGetValue(source, out target);
return target;
}
}
class Program
{
static void Main()
{
Expression<Func<IGizmo, bool>> expr = g => g.Frobnicate();
var e2 = DelegateConversionVisitor.Convert<IGizmo, Gizmo, bool>(expr);
var gizmo = new Gizmo();
e2.Compile()(gizmo);
}
}