Passing property as parameter - c#

I am creating a merit function calculator, which for the uninitiated takes a selection of properties, and calculates a value based on how close those properties are to some idealized values (the merit function). This then enables the user to find an item that most closely matches their requirements.
This is the code I'd like to use:
public class MeritFunctionLine
{
public Func<CalculationOutput, double> property { get; set; }
public double value { get; set; }
public ComparisonTypes ComparisonType { get; set; }
}
public class MeritFunction
{
public List<MeritFunctionLine> Lines { get; set; }
public double Calculate(CalculationOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(values.property - item.value);
}
return m;
}
}
public class CalculationOutput
{
public double property1 { get; set; }
public double property2 { get; set; }
public double property3 { get; set; }
public double property4 { get; set; }
}
Obviously this doesn't compile as values doesn't contain a member called property, but here is an explanation of what I want to do:
Create a new MeritFunction
Add an arbitrary number of MeritFunctionLines to MeritFunction.Lines
The MeritFunctionLine.property should specify what property of CalculationOutput should be compared in MeritFunction.Calculate
i.e.
MeritFunction mf = new MeritFunction();
mf.Lines.Add(new MeritFunctionLine() { property = x => x.Property1, value = 90, comparisonType = ComparisonTypes.GreaterThan });
mf.Lines.Add(new MeritFunctionLine() { property = x => x.Property3, value = 50, comparisonType = ComparisonTypes.Equals });
CalculationOutput c1 = new CalculationOutput() { property1 = 1, property2 = 20, property3 = 150, property4 = 500 };
CalculationOutput c2 = new CalculationOutput() { property1 = 15, property2 = 32, property3 = 15, property4 = 45 };
double value1 = mf.Calculate(c1);
double value2 = mf.Calculate(c2);
I am not asking how to pass a property as a parameter into a function, which is prohibited by C#.

You almost have the right solution already - the only missing piece is how you use the MeritFunctionLine.property property to get the desired value from the CalculationOutput.
In your foreach loop, simply replace the calculation line with
m += Math.Abs(item.property(values) - item.value);
Edit:
Adding Genericity
To address Obsidian Phoenix's comment, you can use this with different classes by making both MeritFunction and MeritFunctionLine generic, so:
public class MeritFunctionLine<TCalcOutput>
{
public Func<TCalcOutput, double> property { get; set; }
public double value { get; set; }
public ComparisonTypes ComparisonType { get; set; }
}
public class MeritFunction<TCalcOutput>
{
public List<MeritFunctionLine<TCalcOutput>> Lines { get; set; }
public double Calculate(TCalcOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(item.property(values) - item.value);
}
return m;
}
}
The rewritten usage example would be
MeritFunction<CalculationOutput> mf = new MeritFunction<CalculationOutput>();
mf.Lines.Add(new MeritFunctionLine<CalculationOutput>() { property = x => x.Property1, value = 90, comparisonType = ComparisonTypes.GreaterThan });
mf.Lines.Add(new MeritFunctionLine<CalculationOutput>() { property = x => x.Property3, value = 50, comparisonType = ComparisonTypes.Equals });
CalculationOutput c1 = new CalculationOutput() { property1 = 1, property2 = 20, property3 = 150, property4 = 500 };
CalculationOutput c2 = new CalculationOutput() { property1 = 15, property2 = 32, property3 = 15, property4 = 45 };
double value1 = mf.Calculate(c1);
double value2 = mf.Calculate(c2);
Some extra convenience
If you have many MeritFunctionLines to add, the syntax above can be a bit tedious. So as a bonus, let's change MeritFunction so that it can be initialized with the list initialization syntax. To do that, we need to make it IEnumerable and give it an Add function:
public class MeritFunction<TCalcOutput> : IEnumerable<MeritFunctionLine<TCalcOutput>>
{
public List<MeritFunctionLine<TCalcOutput>> Lines { get; set; }
public MeritFunction()
{
Lines = new List<MeritFunctionLine<TCalcOutput>>();
}
public void Add(Func<TCalcOutput, double> property, ComparisonTypes ComparisonType, double value)
{
Lines.Add(new MeritFunctionLine<CalculationOutput>
{
property = property,
value = value,
comparisonType = ComparisonType
});
}
public double Calculate(TCalcOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(item.property(values) - item.value);
}
return m;
}
public IEnumerator<MeritFunctionLine<TCalcOutput>> GetEnumerator()
{
return List.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Note that the Add method receives the parameters in a different order - you'll understand why when you look at the usage. Quite a bit of extra code, but now creating our MeritFunction is a bit nicer:
MeritFunction<CalculationOutput> mf = new MeritFunction<CalculationOutput>
{
{ x => x.Property1, ComparisonTypes.GreaterThan, 90 },
{ x => x.Property3, ComparisonTypes.Equals, 50 }
};
Note, all code untested. Use at own risk :)

It is possible, but it's not exactly pretty. You can make use of Expression<Func<double>> to pass in the property, then use reflection to pull the value back out.
NB: I have not coded this to accomodate for error scenarios, you may want to add additional checks.
class Program
{
static void Main(string[] args)
{
MeritFunction<CalculationOutput> mf = new MeritFunction<CalculationOutput>();
//Create an instance of the object for reference.
var obj = new CalculationOutput();
//Use Lambda to set the Property Expression on the Line, pointing at the Property we are interested in.
mf.Lines.Add(new MeritFunctionLine() { PropertyExpression = () => obj.property1, value = 90, ComparisonType = ComparisonTypes.GreaterThan });
mf.Lines.Add(new MeritFunctionLine() { PropertyExpression = () => obj.property3, value = 50, ComparisonType = ComparisonTypes.Equals });
CalculationOutput c1 = new CalculationOutput() { property1 = 1, property2 = 20, property3 = 150, property4 = 500 };
CalculationOutput c2 = new CalculationOutput() { property1 = 15, property2 = 32, property3 = 15, property4 = 45 };
double value1 = mf.Calculate(c1);
double value2 = mf.Calculate(c2);
Console.WriteLine(value1);
Console.WriteLine(value2);
}
}
public class MeritFunctionLine
{
//Capture an expression representing the property we want.
public Expression<Func<double>> PropertyExpression { get; set; }
public double value { get; set; }
public ComparisonTypes ComparisonType { get; set; }
}
public class MeritFunction<T>
{
public List<MeritFunctionLine> Lines { get; set; }
public MeritFunction()
{
Lines = new List<MeritFunctionLine>();
}
public double Calculate(T values)
{
double m = 0;
foreach (var item in Lines)
{
//Get the Value before calculating.
double value = ExtractPropertyValue(item, values);
m += Math.Abs(value - item.value);
}
return m;
}
/// <summary>
/// Take the Provided Expression representing the property, and use it to extract the property value from the object we're interested in.
/// </summary>
private double ExtractPropertyValue(MeritFunctionLine line, T values)
{
var expression = line.PropertyExpression.Body as MemberExpression;
var prop = expression.Member as PropertyInfo;
double value = (double)prop.GetValue(values);
return value;
}
}
public class CalculationOutput
{
public double property1 { get; set; }
public double property2 { get; set; }
public double property3 { get; set; }
public double property4 { get; set; }
}
public enum ComparisonTypes
{
GreaterThan,
Equals
}
The one gotcha of this method, is that you need to create an instance of the object whilst building up the Lines property, otherwise you can't actually access the property through the lambda.
If you only need this for a single class, then this is likely overkill, but it will work with essentially any class.

Related

Reflection in C#: Grouping properties and calculate sum of another properties

So, I have such class:
public class PaymentsModel
{
[ReportsSummary(isGroupingSource:true)]
public string PaymentType { get; set; }
[ReportsSummary(isGroupingTarget: true)]
public double Amount { get; set; }
public string GuestName { get; set; }
}
I have List of (generic) which contains different objects with different values, for example:
{"Bank", 1, "K"},
{"Card", 2, "C"},
{"Cash", 3, "D"},
{"Bank", 2, "E"},
{"Card", 3, "G"},
I need a method CalculateSum() which will use generic class and reflection, and return Dictionary with grouping by PaymentType, and sum Amount for each PaymentType.
So result should be:
[{"Bank", 3},
{"Card", 5},
{"Cash", 5}]
I created an attribute to understand, which property should be grouped, and which - summed:
class ReportsSummaryAttribute : Attribute
{
public bool IsGroupingSource { get; private set; }
public bool IsGroupingTarget { get; private set; }
public ReportsSummaryAttribute(bool isGroupingSource = false, bool isGroupingTarget = false)
{
IsGroupingSource = isGroupingSource;
IsGroupingTarget = isGroupingTarget;
}
}
But don't understand, how to create correct method.
a possible solution you could adapt:
public class MyGenericClass<T> where T:PaymentsModel//or common baseType
{
public Dictionary<string, double> genericMethod(List<T> source)
{
var result = source.GroupBy(x => x.PaymentType)
.Select(t => new { PaymentType = t.Key, Total = t.Sum(u => u.Amount) })
.ToDictionary(t => t.PaymentType, t => t.Total);
return result;
}
}
:
:
//in processus
var myGenericClass = new MyGenericClass<PaymentsModel>();
var result = myGenericClass.genericMethod(source);

Storing functions in C# class properties?

I need to create a list containing Device objects. These objects have properties that describe their Name, Unit and Conversion. Conversion is a bit special as this is supposed to be a function. For example: If I had a temperature sensor measuing in farenheit, its conversion method should calculate and return the value in celsius. And if I have a moisture sensor, its conversion will be different etc. Below is an example of how I have tried doing this but it doesn't work. I get errors saying that only assignment is allowed on Conversion.
private class Device
{
public string Name { get; set; }
public Action Conversion { get; set; }
public string Unit { get; set; }
}
public static object ParseDecentLab(byte[] bytes)
{
List<Device> deviceList = new List<Device>()
{
new Device()
{
Name = "battery-voltage",
Conversion = (x) => x / 1000,
Unit = "V"
},
new Device()
{
Name = "air-temperature",
Conversion = (x) => (175 * x / 65535) - 45,
Unit = "°C"
}
};
Try this code:
use Func instead of Action.
Func can return value where as Action Can't.
private class Device
{
public string Name { get; set; }
public Func<double,double> Conversion { get; set; }
public string Unit { get; set; }
}
public static object ParseDecentLab(byte[] bytes)
{
List<Device> deviceList = new List<Device>()
{
new Device()
{
Name = "battery-voltage",
Conversion = (x) => x / 1000,
Unit = "V"
},
new Device()
{
Name = "air-temperature",
Conversion = (x) => (175 * x / 65535) - 45,
Unit = "°C"
}
};
}
You want Func<double, double> instead of Action; given double (e.g. 4.5 Volt) return double.
x => x / 1000
On the contrary, Action takes no arguments and returns nothing: () => {...}
Code:
// Let's implement immutable class (assigned once, never change)
// in order to prevent occasional errors like device.Name = ...
private class Device {
public string Name { get; }
public Func<double, double> Conversion { get; }
public string Unit { get; }
// Let's validate the input (at least, for null)
public Device(string name, Func<double, double> conversion, string unit) {
if (null == name)
throw new ArgumentNullException(nameof(name));
else if (null == conversion)
throw new ArgumentNullException(nameof(conversion));
else if (null == unit)
throw new ArgumentNullException(nameof(unit));
Name = name;
Conversion = conversion;
Unit = unit;
}
}
...
List<Device> deviceList = new List<Device>() {
new Device("battery-voltage", x => x / 1000, "V"),
new Device("air-temperature", x => (175 * x / 65535) - 45, "°C"),
};
Possible usage:
// What device should we use if we want °C unit?
Device temperature = deviceList
.FirstOrDefault(item => item.Unit == "°C");
byte[] dataToConvert = new byte[] {123, 45, 79};
// Device found
if (temperature != null) {
// Converting: for each value in dataToConvert we obtain corresponding t value
foreach (var value in dataToConvert) {
double t = temperature.Conversion(value);
...
}
}
Or you can even have an array of converted values (double[]) with a help of Linq:
byte[] dataToConvert = new byte[] {123, 45, 79};
// Let's throw exception if device has not been found
Device temperature = deviceList
.First(item => item.Unit == "°C");
double[] results = dataToConvert
.Select(v => temperature.Convert(v))
.ToArray();

C# Reactive Extensions (rx) FirstOrDefault enumerates entire collection

It seems that the expected behavior of FirstOrDefault is to complete after finding an item that matches the predicate and the expected behavior of concat is to evaluate lazily. However, the following example enumerates the entire collection even though the predicate matches the first item.
(Thanks for the friendlier code Shlomo)
void Main()
{
var entities = Observable.Defer(() => GetObservable().Concat());
Entity result = null;
var first = entities.FirstOrDefaultAsync(i => i.RowId == 1).Subscribe(i => result = i);
result.Dump();
buildCalled.Dump();
}
// Define other methods and classes here
public IEnumerable<IObservable<Entity>> GetObservable()
{
var rows = new List<EntityTableRow>
{
new EntityTableRow { Id = 1, StringVal = "One"},
new EntityTableRow { Id = 2, StringVal = "Two"},
};
return rows.Select(i => Observable.Return(BuildEntity(i)));
}
public int buildCalled = 0;
public Entity BuildEntity(EntityTableRow entityRow)
{
buildCalled++;
return new Entity { RowId = entityRow.Id, StringVal = entityRow.StringVal };
}
public class Entity
{
public int RowId { get; set; }
public string StringVal { get; set; }
}
public class EntityTableRow
{
public int Id { get; set; }
public string StringVal { get; set; }
}
Is this the expected behavior? Is there a way to defer the enumeration of the objects (specifically the building in this case) until truly needed?
The following is Linqpad-friendly code equivalent to what you have:
void Main()
{
var entities = Observable.Defer(() => GetObservable().Concat());
Entity result = null;
var first = entities.FirstOrDefaultAsync(i => i.RowId == 1).Subscribe(i => result = i);
result.Dump();
buildCalled.Dump();
}
// Define other methods and classes here
public IEnumerable<IObservable<Entity>> GetObservable()
{
var rows = new List<EntityTableRow>
{
new EntityTableRow { Id = 1, StringVal = "One"},
new EntityTableRow { Id = 2, StringVal = "Two"},
};
return rows.Select(i => Observable.Return(BuildEntity(i)));
}
public int buildCalled = 0;
public Entity BuildEntity(EntityTableRow entityRow)
{
buildCalled++;
return new Entity { RowId = entityRow.Id, StringVal = entityRow.StringVal };
}
public class Entity
{
public int RowId { get; set; }
public string StringVal { get; set; }
}
public class EntityTableRow
{
public int Id { get; set; }
public string StringVal { get; set; }
}
If you change GetObservable to the following, you'll get the desired result:
public IObservable<IObservable<Entity>> GetObservable()
{
var rows = new List<EntityTableRow>
{
new EntityTableRow { Id = 1, StringVal = "One"},
new EntityTableRow { Id = 2, StringVal = "Two"},
};
return rows.ToObservable().Select(i => Observable.Return(BuildEntity(i)));
}
It appears the implementation of Concat<TSource>(IEnumerable<IObservable<TSource>>) is eager in evaluating the enumerable, whereas the implementation of Concat<TSource>(IObservable<IObservable<TSource>>) and ToObservable<TSource>(IEnumerable<TSource>) maintain laziness appropriately. I can't say I know why.

How store From-To value and result in an array

I want to store some items with fields "fromValue", "ToValue" , "Info" in an array and write a routine to search an input "value" between "FromValue" & "ToValue" and return "Info" field. I need fast searchable container.
FromValue,ToValue,Info
10,20,TX
24,56,NY
input =34 returns NY
Thanks
ok simple, this class defines your generic range.
public class Range<TValue, TInfo>
{
private readonly IComparer<TValue> comparer;
public Range(IComparer<TValue> comparer)
{
this.comparer = comparer;
}
public Range(IComparer<TValue> comparer)
: this(Comparer<TValue>.Default)
{
}
public TValue From { get; set; }
public TValue To { get; set; }
public TInfo Info { get; set; }
public bool InRange(T value, bool inclusive = true)
{
var lowerBound = this.comparer.Compare(value, this.From);
if (lowerBound < 0)
{
return false;
}
else if (!inclusive && lowerBound == 0)
{
return false;
}
var upperBound = this.comparer.Compare(value, this.To);
if (upperBound > 0)
{
return false;
}
else if (!inclusive && upperBound == 0)
{
return false;
}
return true;
}
}
So, you can have a sequence of ranges,
IEnumerable<Range<int, string>> ranges = ...
To find all the info values in range you can do,
var rangesInRange = ranges.Where(r => r.InRange(42)).Select(r => r.Info);
You could make a specialised container to improve this operation.
Class:
public class Information
{
public int FromValue { get; set; }
public int ToValue { get; set; }
public string Info { get; set; }
}
Search:
List<Information> Informations = new List<Information>();
Information infoObj = new Information();
infoObj.FromValue = 10;
infoObj.ToValue = 20;
infoObj.Info = "TX";
Informations.Add(infoObj);
Information infoObj2 = new Information();
infoObj2.FromValue = 24;
infoObj2.ToValue = 56;
infoObj2.Info = "NY";
Informations.Add(infoObj);
//passing sample input which lies between fromvalue and tovalue
int sampleInput = 15;
var result = Informations.FirstOrDefault(x => x.FromValue < sampleInput && sampleInput < x.ToValue);
This is pretty straight forward.
In the most simple scenario just create a class Item
public class Item
{
public int Id { get; set; }
public int FromValue { get; set; }
public int ToValue { get; set; }
public string Info { get; set; }
}
With this you can initialize your collection of type List<T>
List<Item> Items = new List<Item>()
{
new Item() {Id = 1, FromValue = 10, ToValue = 20, Info = "TX"}
new Item() {Id = 2, FromValue = 24, ToValue = 56, Info = "NY"}
new Item() {Id = 3, FromValue = 15, ToValue = 34, Info = "FL"}
};
And with this you can query it to your hearts content.
var itemsFromFlorida = Items.Where(it => it.Info == "FL");

Using contravariance with Func<T, object> selector property

I am designing a generic column definitions class which will act as a selector of properties from entities, all this to make it easier to manage grid presentations of different aspects in a LOB application.
Unfortunately I hit a wall trying to use generic parameter in a class which will be contained in a collection. Example implementation for SettingsContext class below explains what is happening:
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T>: IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public class ColumnSet
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<object>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
// Cannot implicitly convert type 'DisplayColumn<System.Configuration.SettingsContext>' to 'IDisplayColumn<object>'.
// An explicit conversion exists (are you missing a cast?)
IDisplayColumn<object> testSingleColumn = new DisplayColumn<SettingsContext> {Title = "Test", Selector = x => x.Values };
// another test with other type used as a source which should be assignable to DisplayColumn<object>
testSingleColumn = new DisplayColumn<SettingsProvider> { Title="Another test", Selector = x => x.ApplicationName };
// Cannot implicitly convert type 'System.Collections.Generic.List<IDisplayColumn<System.Configuration.SettingsContext>>'
// to 'System.Collections.Generic.IEnumerable<IDisplayColumn<object>>'.
// An explicit conversion exists (are you missing a cast?)
var columnSets = new List<ColumnSet>
{
new ColumnSet
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext /* or object */>>
{
new DisplayColumn<SettingsContext> {Title = "Column 1", Order = 1, Selector = x => x.IsReadOnly },
new DisplayColumn<SettingsContext> {Title = "Column 2", Order = 2, Selector = x => x.IsSynchronized },
new DisplayColumn<SettingsContext> {Title = "Column 3", Order = 3, Selector = x => x.Keys }
}
}
};
}
}
How I understand the purpose of covariance and contravariance this is really expected - out parameter should be used for IDisplayColumn testSingleColumn = new DisplayColumn assignment but I need to make Func in parameter generic, out will always be an object.
How to implement such scenario, would it require implementing custom Func or maybe dotnet has already a type suited for such purpose?
Currently the only solution I can see is to create non-generic DisplayColumn class with Func< object, object > Selector property and casting argument to a concrete type in each assignment which is obviously not a great solution. Another option would be to inherit base non-generic DisplayColumn class and put generic selector in inherited generic class but then using this expression when presenting data would require invoking generic method in inherited generic class which is really unacceptable by performance and code quality standards.
If you make your ColumnSet generic as well, then you can specify the type used for the columns enumerable that it returns. The code below will compile, and I think achieve what you are after.
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T>: IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public class ColumnSet<T>
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<T>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
IDisplayColumn<SettingsContext> testSingleColumn = new DisplayColumn<SettingsContext> { Title = "Test", Selector = x => x.Values };
var columnSets = new List<ColumnSet<SettingsContext>>
{
new ColumnSet<SettingsContext>
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext>>
{
new DisplayColumn<SettingsContext> {Title = "Column 1", Order = 1, Selector = x => x.IsReadOnly },
new DisplayColumn<SettingsContext> {Title = "Column 2", Order = 2, Selector = x => x.IsSynchronized },
new DisplayColumn<SettingsContext> {Title = "Column 3", Order = 3, Selector = x => x.Keys }
}
}
};
}
}
After thorough investigation I found out the solution would require mixing covariance and contravariance which is not supported currently. The closest solution (which compiles) actually does not allow easy access to IDisplayColumn.Selector as T argument in IColumnSet.Columns will be visible as object not IDisplayColumn so it's not an option:
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T> : IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public interface IColumnSet<out T>
{
Type TypeHandled { get; }
IEnumerable<T> Columns { get; }
}
public class ColumnSet<T> : IColumnSet<IDisplayColumn<T>>
{
public Type TypeHandled
{
get
{
return typeof(T);
}
}
public IEnumerable<IDisplayColumn<T>> Columns { get; set; }
}
I ended up translating Func<,> using expressions when creating which is a one-time operation with minimal overhead of casting when using selector:
public interface IDisplayColumn
{
string Title { get; set; }
bool Visible { get; set; }
int Order { get; set; }
Func<object, object> Value { get; }
T GetValue<T>(object source);
}
public class DisplayColumn<T>: IDisplayColumn
{
public string Title { get; set; }
public bool Visible { get; set; }
public int Order { get; set; }
public Func<object, object> Value { get; set; }
public override string ToString()
{
return Title;
}
public TValue GetValue<TValue>(object source)
{
return (TValue)Convert.ChangeType(Value(source), typeof(TValue));
}
public Func<T, object> Selector
{
set
{
Value = value.ConvertObject<T>();
}
}
}
public interface IColumnSet
{
Type TypeHandled { get; }
IEnumerable<IDisplayColumn> Columns { get; }
}
public class ColumnSet<T>: IColumnSet
{
public Type TypeHandled
{
get
{
return typeof(T);
}
}
public IEnumerable<IDisplayColumn> Columns { get; set; }
}
public static Func<object, object> ConvertObject<T>(this Func<T, object> func)
{
Contract.Requires(func != null);
var param = Expression.Parameter(typeof(object));
var convertedParam = new Expression[] { Expression.Convert(param, typeof(T)) };
Expression call;
call = Expression.Convert(
func.Target == null
? Expression.Call(func.Method, convertedParam)
: Expression.Call(Expression.Constant(func.Target), func.Method, convertedParam)
, typeof(object));
var delegateType = typeof(Func<,>).MakeGenericType(typeof(object), typeof(object));
return (Func<object, object>)Expression.Lambda(delegateType, call, param).Compile();
}
And the example of usage:
private class TestObject1
{
public int Id { get; set; }
public string Name { get; set; }
}
IDisplayColumn objectColumn = new DisplayColumn<TestObject1> { Title = "Column 1", Selector = (x) => x.Name };
var columnSets = new List<IColumnSet>
{
new ColumnSet<TestObject1>
{
Columns = new List<IDisplayColumn>
{
new DisplayColumn<TestObject1> { Title = "Column 1", Order = 3, Selector = x => x.Id },
new DisplayColumn<TestObject1> { Title = "Column 2", Order = 2, Selector = x => x.Name },
new DisplayColumn<TestObject1> { Title = "Column 3", Order = 1, Selector = x => x.Id.ToString(CultureInfo.InvariantCulture) + x.Name.ValueOrEmpty() },
}
}
};
So I will give myself the credit for this problem but if somebody can suggest a nicer solution using generics and variance, please feel free to post it as I will be happy to change the solution.

Categories

Resources