whoami
whoami

Reputation: 1899

Only get filtered elements from class properties

Below is how the code looks like. Note that all of the EmployeeSomethingA, EmployeeSomethingB, EmployeeSomethingC class have a common EmployeeID property.

class EmployeesData
    {
        public List<EmployeeSomethingA> EmployeeSomethingAs { get; set; }
        public List<EmployeeSomethingB> EmployeeSomethingBs { get; set; }
        public List<EmployeeSomethingC> EmployeeSomethingCs { get; set; }
    }

    class EmployeeSomethingA
    {
        public int EmployeeID { get; set; }
        public string SomethingA { get; set; }
    }

    class EmployeeSomethingB
    {
        public int EmployeeID { get; set; }
        public string SomethingB { get; set; }
        public float SomethingBA { get; set; }
    }
    class EmployeeSomethingC
    {
        public int EmployeeID { get; set; }
        public string SomethingC { get; set; }
        public Guid SomethingCA { get; set; }
        public double SomethingCB { get; set; }
    }

I want add ability on EmployeesData class so that I can retrieve filtered from EmployeeSomethingAs, EmployeeSomethingBs and EmployeeSomethingCs for a particular EmployeeID. I am not sure I can use linq where in this case but I would like is something as follows.

EmployeeDataInstance.Where ( x => x.EmployeeID > 2);

This should return only an EmployeeData instance where EmployeeSomethingAs, EmployeeSomethingBs and EmployeeSomethingCs will contains data with EmployeeID > 2. I don't know if implementing IEnumerable can get me this ability. Any idea how this could be accomplished?

Upvotes: 2

Views: 79

Answers (2)

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

You can try something like that;

Create Employee class that contains shared property EmployeeID and other classes are derived from it.

class Employee
{
    public int EmployeeID { get; set; }
}
class EmployeeSomethingA : Employee
{
    public string SomethingA { get; set; }
}

class EmployeeSomethingB : Employee
{
    public string SomethingB { get; set; }
}
class EmployeeSomethingC : Employee
{
    public string SomethingC { get; set; }
}

And create Where method to perform where clause for EmployeesData class;

class EmployeesData
{
    public List<EmployeeSomethingA> EmployeeSomethingAs { get; set; }
    public List<EmployeeSomethingB> EmployeeSomethingBs { get; set; }
    public List<EmployeeSomethingC> EmployeeSomethingCs { get; set; }

    public void Where(Func<Employee, bool> predicate)
    {
        EmployeeSomethingAs = EmployeeSomethingAs.Where((Func<EmployeeSomethingA, bool>)predicate).ToList();
        EmployeeSomethingBs = EmployeeSomethingBs.Where((Func<EmployeeSomethingB, bool>)predicate).ToList();
        EmployeeSomethingCs = EmployeeSomethingCs.Where((Func<EmployeeSomethingC, bool>)predicate).ToList();
    }
}

Usage;

employeesData.Where(x => x.EmployeeID == 1);

EDIT

If you want to filter the list properties as new EmployeesData instance you can modify Where method like this;

public EmployeesData Where(Func<Employee, bool> predicate)
{
    return new EmployeesData
    {
        EmployeeSomethingAs = EmployeeSomethingAs.Where((Func<EmployeeSomethingA, bool>)predicate).ToList(),
        EmployeeSomethingBs = EmployeeSomethingBs.Where((Func<EmployeeSomethingB, bool>)predicate).ToList(),
        EmployeeSomethingCs = EmployeeSomethingCs.Where((Func<EmployeeSomethingC, bool>)predicate).ToList()
    };
}

var newEmployeesData = employeesData.Where(x => x.EmployeeID == 1);

Upvotes: 3

JuanR
JuanR

Reputation: 7803

You can get away with using Linq and a single predicate if you use a base class and don't care about the type when consuming the results. I am providing a solution for that and the case where you do care about the types:

public class EmployeesData
{
    public List<EmployeeSomethingA> EmployeeSomethingAs { get; private set; }
    public List<EmployeeSomethingB> EmployeeSomethingBs { get; private set; }
    public List<EmployeeSomethingC> EmployeeSomethingCs { get; private set; }

    //Single predicate alternative. 
    public IEnumerable<EmployeeBase> Where(Func<EmployeeBase, bool> selector)
    {
        return EmployeeSomethingAs.Where(selector)
            .Union(EmployeeSomethingBs.Where(selector))
            .Union(EmployeeSomethingCs.Where(selector));
    }

    //Typed alternative
    public SearchResult FindById(int id)
    {
        var a = EmployeeSomethingAs.Where(e => e.EmployeeID == id);
        var b = EmployeeSomethingBs.Where(e => e.EmployeeID == id);
        var c = EmployeeSomethingCs.Where(e => e.EmployeeID == id);

        return new SearchResult(a, b, c);
    }
}

public class SearchResult
{
    public SearchResult(IEnumerable<EmployeeSomethingA> a, IEnumerable<EmployeeSomethingB> b, IEnumerable<EmployeeSomethingC> c)
    {
        As = a;
        Bs = b;
        Cs = c;
    }
    public IEnumerable<EmployeeSomethingA> As { get; private set; }
    public IEnumerable<EmployeeSomethingB> Bs { get; private set; }
    public IEnumerable<EmployeeSomethingC> Cs { get; private set; }
}

public class EmployeeSomethingA : EmployeeBase
{

    public string SomethingA { get; set; }
}

public class EmployeeSomethingB : EmployeeBase
{

    public string SomethingB { get; set; }
}
public class EmployeeSomethingC : EmployeeBase
{        
    public string SomethingC { get; set; }
}

public class EmployeeBase
{
    public int EmployeeID { get; set; }
}

Difference in usage:

var data = new EmployeesData();

//This will get me an IEnumerable of EmployeeBase
var results = data.Where(e => e.EmployeeID == 5);

//This will get me a SearchResult object with typed results
var results2 = data.FindById(5);

Upvotes: 1

Related Questions