Reputation: 1395
I am merging some code bases into one and am trying to figure out a clever way to merge some slightly different generic objects into a list that builds some of the UI for filtering.
I have many Manager objects that produce and manage ResultSets that are built on top of some of the application base classes.
Any ideas would be great. I am trying not to refactor old deep code as much as possible.
CityManager is something like
ImAFilterSetManager<ImAFilterSetBase<CityBase>>
and ChainManger is something like
ImAFilterSetManager<ImAFilterSetBase<ChainBase>>
The Manager executes the Initialize and returns a ImAFilterSetBase and wires the handler.
Is there a way to cast to something like below?
ImAFilterSetManager<ImAFilterSetBase<object>>
Execution code
List<object> filters = new List<object>() {
new CityManager(),
new ChainManager(), }
//(XXXX as object fails)
foreach (ImAFilterSetManager<ImAFilterSetBase<XXXX>> filter in filters)
{
var newFilter = filter.Initialize(_Client);
filter.OnResultsChanged += filterResults_Handler;
}
It does seem if use dyanmic i can Initialize (or at least it compliles and runs, havent tried much else) but I'm a little worried that would be bad form or cause side effects.
foreach (dynamic filter in filters)
{
var newFilter = filter.Initialize(_Client);
}
Interfaces for reference ( generic I is a ImAFilterSetBase(CityBase) and generic C would be CityBase or ChainBase class )
public interface ImAFilterSetManager<I>
{
event EventHandler<ResultSetArgs> OnResultsChanged;
I Initialize(IClient client);
}
public interface ImAFilterSetBase<C>
{
string FilterName { get; set; }
List<C> Filter { get; set; }
}
Upvotes: 1
Views: 93
Reputation: 5267
You may think in the Liskov Substitution Principle (SOLID), so a good way is relate the objects via an interface:
//defines the contract
public interface IObjectBase {
//add signatures
}
class CityBase : IObjectBase /*, IAnotherBaseA */ {
//implementation
}
class ChainBase : IObjectBase /*, IAnotherBaseB */ {
//implementation
}
Now we are going to create a constraint for the ImAFilterSetBase
and rename it to AFilterSetBase
public abstract class AFilterSetBase<T> where T : IObjectBase /*, new() */ {
public string FilterName { get; set; }
public IList<T> Filters { get; set; }
}
I am going to redefine the interface ImAFilterSetManager
and rename it to IFilterSetManager
public interface IFilterSetManager {
event EventHandler<ResultSetArgs> OnResultsChanged;
AFilterSetBase<IObjectBase> Initialize(IClient client);
}
Now we can create the classes that implements IFilterSetManager
:
public class CityManager : IFilterSetManager {
public AFilterSetBase<IObjectBase> Initialize(IClient client) {
//TODO: implementation
throw new NotImplementedException();
}
}
//other classes that implements IFilterSetManager
class ChainManager : IFilterSetManager {
public AFilterSetBase<IObjectBase> Initialize(IClient client) {
throw new NotImplementedException();
}
}
Finally, in the end-class we can create the list as follow:
static void Main() {
IClient _client;
//_client = new ...
var filters = new List<IFilterSetManager>() {
new CityManager(),
new ChainManager()
};
foreach (var item in filters) {
var newFilter = item.Initialize(_client);
}
}
An example implementation for CityManager
could be as follow:
class CityFilter : AFilterSetBase<IObjectBase> {
public CityFilter(string filterName) {
this.FilterName = filterName;
this.Filters = new List<IObjectBase>();
}
}
public class CityManager : IFilterSetManager {
public AFilterSetBase<IObjectBase> Initialize(IClient client) {
var item = new CityFilter("City Filters");
item.Filters.Add(new CityBase());
return item;
}
}
And then we can test it:
static void Main(string[] args) {
IClient _client;
_client = null;
var filters = new List<IFilterSetManager>() {
new CityManager(),
new ChainManager()
};
foreach (var item in filters) {
var newFilter = item.Initialize(_client);
System.Console.WriteLine("Filter name: " + newFilter.FilterName);
System.Console.WriteLine("Filters added: " + newFilter.Filters.Count);
}
System.Console.ReadLine();
}
Upvotes: 0
Reputation: 39069
In C#, Generic<A>
and Generic<B>
are not related, unless you make them related. Create another non-generic class (or interface) - FilterSetManager
, and have all your ImAFilterSetManager<T>
derive from that, or implement that.
Then you can have a List<FilterSetManager>
.
Upvotes: 2