The name is a little blurry, so here's the situation:
I'm writing code to use some 'trajectories'. The trajectories are an abstract thing, so I describe them with different interfaces. So I have a code as this:
namespace Trajectories {
public interface IInitial<Atom>
{
Atom Initial { get; set; }
}
public interface ICurrent<Atom>
{
Atom Current { get; set; }
}
public interface IPrevious<Atom>
{
Atom Previous { get; set; }
}
public interface ICount<Atom>
{
int Count { get; }
}
public interface IManualCount<Atom> : ICount<Atom>
{
int Count { get; set; }
}
...
}
Every concrete implementation of a trajectory will implement some of the above interfaces. Here's a concrete implementation of a trajectory:
public class SimpleTrajectory<Atom> : IInitial<Atom>, ICurrent<Atom>, ICount<Atom> {
// ICount
public int Count { get; private set; }
// IInitial
private Atom initial;
public Atom Initial { get { return initial; } set { initial = current = value; Count = 1; } }
// ICurrent
private Atom current;
public Atom Current { get { return current; } set { current = value; Count++; } }
}
Now, I want to be able to deduce things about the trajectories, so, for example I want to support predicates about different properties of some trajectory:
namespace Conditions
{
public interface ICondition<Atom, Trajectory>
{
bool Test(ref Trajectory t);
}
public class CountLessThan<Atom, Trajectory> : ICondition<Atom, Trajectory>
where Trajectory : Trajectories.ICount<Atom>
{
public int Value { get; set; }
public CountLessThan() { }
public bool Test(ref Trajectory t)
{
return t.Count < Value;
}
}
public class CurrentNormLessThan<Trajectory> : ICondition<Complex, Trajectory>
where Trajectory : Trajectories.ICurrent<Complex>
{
public double Value { get; set; }
public CurrentNormLessThan() { }
public bool Test(ref Trajectory t)
{
return t.Current.Norm() < Value;
}
}
}
Now, here's the question: What if I wanted to implement AND predicate? It would be something like this:
public class And<Atom, CondA, TrajectoryA, CondB, TrajectoryB, Trajectory> : ICondition<Atom, Trajectory>
where CondA : ICondition<Atom, TrajectoryA>
where TrajectoryA : // Some interfaces
where CondB : ICondition<Atom, TrajectoryB>
where TrajectoryB : // Some interfaces
where Trajectory : // MUST IMPLEMENT THE INTERFACES FOR TrajectoryA AND THE INTERFACES FOR TrajectoryB
{
public CondA A { get; set; }
public CondB B { get; set; }
public bool Test(ref Trajectory t) {
return A.Test(t) && B.Test(t);
}
}
How can I say: support only these trajectories, for which the arguments of AND are ok?
So I can be able to write:
var vand = new CountLessThan(32) & new CurrentNormLessThan(4.0);
I think if I create an overall interface for every subset of interfaces, I could be able to do it, but it will become quite ugly.