Search code examples
c#.netgenericsgeneric-collections

How to filter a collection inside a generic method


I have a two class which is having following properties

 Class A
  {
      public int CustID { get; set; }
      public bool isProcessed { get; set; }
  }
  Class B
  {
      public int EmpId{ get; set; }
      public bool isProcessed { get; set; }
  }

I created one generic method which accepts all these classes.'isProcessed' property is common in both these classes.

public void ProceesData<T>(IList<T> param1, string date1)
{

}

I need following things

  1. Inside ProcessData method i want to filter items which is having isProcessed flag is "True".
  2. Also i want to iterate this collection and need to set values for IsProcessed property.

Note: I am preferring solution using reflection,since property name is constant (ie "IsProcessed")

Can anyone help on this.


Solution

  • The easiest way is to ensure that both classes implement a common interface and constrain your generic method. For example:

    public interface IProcessable
    {
        bool isProcessed { get; set; }
    }
    public class A : IProcessable
    {
        public int CustID { get; set; }
        public bool isProcessed { get; set; }
    }
    
    public class B : IProcessable
    {
        public int EmpId { get; set; }
        public bool isProcessed { get; set; }
    }
    

    Now your method would look like this:

    public void ProceesData<T>(IList<T> param1, string date1)
        where T : IProcessable // <-- generic constraint added
    {
        foreach (var element in param1)
        {
            element.isProcessed = true;
        }
    }
    

    Another option which is more useful if you cannot use an interface or the property names vary, is to pass in an Action<T> as a parameter to your method. For example:

    public void ProceesData<T>(IList<T> param1, string date1, Action<T> func)
    {
        foreach (var element in param1)
        {
            func(element);
        }
    }
    

    And call it like this:

    ProceesData<A>(list, "", x => x.isProcessed = true);