Hi Peter,
I would abstract out the idea of filtering from the collection class, so
that the logic for filtering lives inside a different object say a UserFilter
class, this class would have one method called Filter which takes a user as a
parameter. The filter method would then return true if the user met the
criteria and false otherwise. You would then have deriviations of this class
like NameFilter, EmailFilter and ApprovedFilter.
Your Users class would then have one function called Filter which then takes
a UserFilter as a parameter i.e. Filter(UserFilter filter).
See the example below (the formatting might be a bit messed up):
using System;
namespace ConsoleApplication11
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
User userMark, userBob, userFrank;
userMark = new User("mark", "da*********@gmail.com", true);
userBob = new User("bob", "bo*@example.org", true);
userFrank = new User("frank", "fr***@example.org", false);
Users userCollection = new Users();
userCollection.Add(userMark);
userCollection.Add(userBob);
userCollection.Add(userFrank);
NameFilter nameFilter = new NameFilter("mark");
Users usersFilteredByName = userCollection.Filter(nameFilter, true);
EmailFilter emailFilter = new EmailFilter("da*********@gmail.com");
Users usersFilteredByEmail = userCollection.Filter(emailFilter, true);
ApprovalFilter approvalFilter = new ApprovalFilter(true);
Users usersFilteredByApproval = userCollection.Filter(approvalFilter, true);
Console.ReadLine();
}
}
public abstract class UserFilter
{
protected string _criteria;
protected UserFilter(){}
protected UserFilter(string criteria)
{
_criteria = criteria;
}
public abstract bool Filter(User u);
}
public class NameFilter : UserFilter
{
public NameFilter(string criteria) : base(criteria)
{}
public override bool Filter(User u)
{
return u.DisplayName.IndexOf(_criteria) >= 0;
}
}
public class EmailFilter : UserFilter
{
public EmailFilter(string criteria) : base(criteria)
{}
public override bool Filter(User u)
{
return u.Email.IndexOf(_criteria) >= 0;
}
}
public class ApprovalFilter : UserFilter
{
private bool _approvalCriteria;
public ApprovalFilter(bool criteria)
{
_approvalCriteria = criteria;
}
public override bool Filter(User u)
{
return u.Approved == _approvalCriteria;
}
}
public class User
{
private string _displayName, _email;
private bool _approved;
public User(string displayName, string email, bool approved)
{
this._displayName = displayName;
this._email = email;
this._approved = approved;
}
public string DisplayName
{
get { return _displayName; }
}
public string Email
{
get { return _email; }
}
public bool Approved
{
get { return _approved; }
}
}
public class Users : System.Collections.CollectionBase
{
public User this[int index]
{
get { return (User)(List[index]); }
set { List[index] = value; }
}
public Users Filter(UserFilter filter, bool exclude)
{
Users _tmp;
if (exclude)
{
_tmp = this.Clone();
foreach (User _user in this)
{
if (filter.Filter(_user))
{
_tmp.Remove(_user);
}
}
}
else
{
_tmp = new Users();
foreach (User _user in this)
{
if (filter.Filter(_user))
{
_tmp.Add(_user);
}
}
}
return _tmp;
}
public Users Clone()
{
Users _tmp = new Users();
foreach (User _user in this)
{
_tmp.Add(_user);
}
return _tmp;
}
public int Add(User value)
{
return List.Add(value);
}
public void Remove(User value)
{
List.Remove(value);
}
}
}
Also, there was a small error in the code you published, in the
constructor you have:
public User(string displayName, string email, bool approved)
{
this._displayName = displayName;
this._email = email;
this._approved = _approved;
}
you need to change the appoved line to say:
this._approved = approved not this._approved = _approved
Hope that helps
Mark R Dawson
http://www.markdawson.org
"Peter" wrote:
Hi,
I have two simple classes called 'User' and 'Users', the entire code for
both classes is shown below.
****======== User.cs ========****
public class User
{
private string _displayName, _email;
private bool _approved;
public User(string displayName, string email, bool approved)
{
this._displayName = displayName;
this._email = email;
this._approved = _approved;
}
public string DisplayName
{
get { return _displayName; }
}
public string Email
{
get { return _email; }
}
public bool Approved
{
get { return _approved; }
}
}
****======== Users.cs ========****
public class Users : System.Collections.CollectionBase
{
public User this[int index]
{
get { return (User)(List[index]); }
set { List[index] = value; }
}
public Users FilterByDisplayName(string criteria, bool exclude)
{
Users _tmp;
if (exclude)
{
_tmp = this.Clone();
foreach (User _user in this)
{
if (_user.DisplayName.IndexOf(criteria) >= 0)
_tmp.Remove(_user);
}
}
else
{
_tmp = new Users();
foreach (User _user in this)
{
if (_user.DisplayName.IndexOf(criteria) >= 0)
_tmp.Add(_user);
}
}
return _tmp;
}
public Users FilterByEmail(string criteria, bool exclude)
{
Users _tmp;
if (exclude)
{
_tmp = this.Clone();
foreach (User _user in this)
{
if (_user.Email.IndexOf(criteria) >= 0)
_tmp.Remove(_user);
}
}
else
{
_tmp = new Users();
foreach (User _user in this)
{
if (_user.Email.IndexOf(criteria) >= 0)
_tmp.Add(_user);
}
}
return _tmp;
}
public Users FilterByApproved(bool criteria, bool exclude)
{
Users _tmp;
if (exclude)
{
_tmp = this.Clone();
foreach (User _user in this)
{
if (_user.Approved == criteria)
_tmp.Remove(_user);
}
}
else
{
_tmp = new Users();
foreach (User _user in this)
{
if (_user.Approved == criteria)
_tmp.Add(_user);
}
}
return _tmp;
}
public Users Clone()
{
Users _tmp = new Users();
foreach (User _user in this)
{
_tmp.Add(_user);
}
return _tmp;
}
public int Add(User value)
{
return List.Add(value);
}
public void Remove(User value)
{
List.Remove(value);
}
}
On the 'Users' class I have three methods (FilterByDisplayName,
FilterByEmail and FilterByApproved) which basically do the same thing except
they work on a different field on the 'User' class, and in the case of
FilterByApproved on a different data type (bool instead of string). I cannot
find an elegant way to combine these three methods into one method called
Filter(), is there an elegant way of combining these three methods into one
using C# 2003?
Many Thanks,
Peter