EDIT:
This is passive view code.
We want to be able to switch from one Form Type (Windows.Forms, Gtk.Forms, etc.) to another and also want to be able to easily switch from hibernate to ado.net or something else in the future.
I would prefer a mix methods who take fixed parameters and generic ones which taking a list of search parameters.
For example GetSomethingByID just would get one int as a parameter and return a Model.
But when I want so search an address (at least two tables are involed). One which holds address data like addressno., searchname and so on. And another table which holds name1, name2, etc. Then I would get a method with an horrible amount of parameters.
And at this point I'm not extending any of the two tables.(!)
We don't like methods with more than 4 parameters. So we created a "QueryMethodParameter" object which we use from our views.
I will give an example, it's easier for me to show than to explain what we do.
This is executred when you search an address in our view.
p.Items.Add(new QueryMethodParameterItem("Address", "AddressNumber", addressNumber));
p.Items.Add(new QueryMethodParameterItem("Address", "Searchname", searchName));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Name1", name1));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Name2", name2));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Name3", name3));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Street", street));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Zipcode", zipcode));
p.Items.Add(new QueryMethodParameterItem("MailingAddress", "Location", location));
((AddressSearchPresenter)this.Presenter).DoAddressSearch(p);
AddressSearchPresenter
public void DoAddressSearch(QueryMethodParameter p)
{
IAddressService addrService = (IAddressService)ApplicationController.GetInstance().ServiceFactory.GetService(typeof(Model.Address), this.ServiceContext);
IListEx<Model.Address> erg = addrService.LoadAddresses(p);
this.SetModel(erg);
_viewItems = new AddressSearchViewItems(erg);
this.ModelToView();
}
AddressService
public IListEx<Model.Address> LoadAddresses(QueryMethodParameter p)
{
ICriteria ca = this.ServiceFactory.CreateCriteria(this.Context, typeof(Model.Address));
ICriteria ma = null;
for (int i = 0; i < p.Items.Count; i++)
{
object val = p.Items[i].Value;
if (val == null)
{
throw new NullReferenceException();
}
if (val.GetType() == typeof(string))
{
if (!val.ToString().EndsWith("%"))
{
val = val.ToString() + "%";
}
if (!val.ToString().StartsWith("%"))
{
val = "%" + val.ToString();
}
}
if (p.Items[i].ModelName == "Address")
{
ca.Add(Expression.Like(p.Items[i].PropertyName, val));
}
else if (p.Items[i].ModelName == "MailingAddress")
{
if (ma == null)
{
ma = ca.CreateCriteria("MailingAddress", "MailingAddress");
}
ma.Add(Restrictions.Like(p.Items[i].ModelName + "." + p.Items[i].PropertyName, val));
}
else
{
throw new NotImplementedException();
}
}
ca.Add(Expression.Gt("AddressID", 0));
return ca.ListEx<Model.Address>();
}
There're still some things we don't like. For example we've to hardcode Modelnames in our Service. --> Bad
We'll possible change this in the future to generated classes with static strings or enums, to get compiler errors when a field name is changed.
So the second approach in general looks better. But you still need a solution for many, many search parameters. A simple ID is the simplest example.