0

How can I pass a field (via lambda expression) into a method and then use that field as part of a linq query?

I would like to call the method something like

IDictionary<string, string> stuff = foo(items, otherItems, otherItems => otherItems.FieldToUse)

I'm not sure how I would write the method, but I would want to use it sort of like the code below. I know I could use generics and pass the field name (via a string) into the method, but even then I don't know how I would use it in the linq query as follows. Also, I like using lambda, since I could just rename the field anytime I choose.

private IDictionary<string, string> foo<TModel>(IEnumerable<string> items, IEnumerable<TModel> otherItems, object FieldToUse)
    {
        //this will return a list of key value pairs of rowIDs and equipment
        IDictionary<string, string> x = (from o in otherItems
                                         join i in items on o.FieldToUse.ToString() equals i //joining on the equipment assetcode
                                         select new { rowID = o.RowID, item = i }).ToDictionary(k => k.rowID.ToString(), v => v.item);
        return x;
    }

Clarification: FieldToUse is a property or field of TModel

4
  • Question is not very clear. FieldsToUse is a type in otherItems ? When you are passing otherItems, there is no need to pass the field. Commented Sep 1, 2016 at 15:26
  • I don't always want to call the method using the same property, even if I am using the same type for TModel. Sometimes I want to use one property and sometimes another property Commented Sep 1, 2016 at 15:31
  • I think you want to use a selector. An example would be LINQs OrderBy method where you would call .OrderBy(obj => obj.Property); is that what you are looking for? Commented Sep 1, 2016 at 15:47
  • Do you need this to work against LINQ to Entities/SQL? Or is it enough to work against normal objects? Commented Sep 1, 2016 at 15:54

1 Answer 1

3

Use a Func Delegate

Change the last parameter in method foo to

Func<TModel, String> FieldToUse

and in the LINQ query call the function

FieldToUse(o)

Here is the entire method foo

private IDictionary<string, string> foo<TModel>(IEnumerable<string> items,
  IEnumerable<TModel> otherItems,
  Func<TModel, String> FieldToUse)
{
  //this will return a list of key value pairs of rowIDs and equipment
  IDictionary<string, string> x = (from o in otherItems
                                   join i in items on FieldToUse(o) equals i //joining on the equipment assetcode
                                   select new { rowID = o.RowID, item = i })
                                   .ToDictionary(k => k.rowID.ToString(), v => v.item);
  return x;
}

This is how you can use it

public void DoStuff()
{
  string[] items = { "abc", "def", "ghi" };
  List<Model> otherItems = new List<Model> { 
        new Model() { Field1 = "abc", Field2 = "xyz" }, 
        new Model() { Field1 = "abc", Field2 = "xyz" } };

  var result = foo<Model>(items, otherItems, a => a.Field2);
}

class Model 
{
  public string Field1 { get; set; }
  public string Field2 { get; set; }
}

You will have another problem though. The generic TModel does not have RowID. Perhaps provide a generic where constraint for TModel.

The code then becomes

 private IDictionary<string, string> foo<TModel>(IEnumerable<string> items,
  IEnumerable<TModel> otherItems,
  Func<TModel, String> FieldToUse) where TModel : BaseModel
{
  //this will return a list of key value pairs of rowIDs and equipment
  IDictionary<string, string> x = (from o in otherItems
                                   join i in items on FieldToUse(o) equals i //joining on the equipment assetcode
                                   select new { rowID = o.RowID, item = i })
                                   .ToDictionary(k => k.rowID.ToString(), v => v.item);
  return x;
}

class BaseModel
{
  public int RowID { get; set; }
}
class Model : BaseModel
{
  public string Field1 { get; set; }
  public string Field2 { get; set; }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.