I’ve been building a small access rules module for a project where every particular rule is reflected by a generic Rule<TEntity> object. The rule takes a delegate to execute a certain logic.
There is a RulesContext class that provides methods to check access to a certain entity “foo” like this:
rulesContext.CanIRead<Foo>(myFoo);
My intention was to store all rules build during a setup process into one collection. But every approach I tried lead to a dead end.
I thought of something like:
IDictionary<Type, Rule<object>> _rules = new Dictionary<Type, Rule<object>>();
and:
var fooRule = new Rule<Foo>(foo => foo.FullfillsACertainFooCriterion())
_rules.Add(typeof(Foo), fooRule);
The CanIRead implementation would make sure to use the dictionary properly:
public bool CanIRead<TEntity>(TEntity entity)
{
var rule = _rules[typeof(entity)];
return rule.CanIRead(entity);
}
But the compiler does not like this: Rule<Foo> cannot be assigned to a parameter of type Rule<object>. Which kind of makes sense since it would break the contract (which says that I can use the dictionary’s methods with any object as parameter which does not hold true for the fooRule which only accepts Foo typed objects. – Liskov principle)
However I cannot think of a way to solve this. How could I store Rule objects with different types in one collection?
Instead of using
IDictionary<Type, object>which could hold anything (e.g.DateTime) as a value in the dictionary, you could make the values strictly Rule objectsHere