我一直在为一个项目构建一个小型访问规则模块,其中每个特定规则都由通用 Rule<TEntity> 反射(reflect)目的。该规则采用委托(delegate)来执行特定逻辑。
有一个RulesContext提供方法来检查对特定实体“foo”的访问的类,如下所示:
rulesContext.CanIRead<Foo>(myFoo);
我的意图是将设置过程中构建的所有规则存储到一个集合中。但我尝试过的每一种方法都会走向死胡同。
我想到了这样的事情:
IDictionary<Type, Rule<object>> _rules = new Dictionary<Type, Rule<object>>();
和:
var fooRule = new Rule<Foo>(foo => foo.FullfillsACertainFooCriterion())
_rules.Add(typeof(Foo), fooRule);
CanIRead实现将确保正确使用字典:
public bool CanIRead<TEntity>(TEntity entity)
{
var rule = _rules[typeof(entity)];
return rule.CanIRead(entity);
}
但编译器不喜欢这样:Rule<Foo>不能分配给 Rule<object> 类型的参数.哪一种有意义,因为它会破坏契约(它说我可以使用字典的方法和任何对象作为参数,这对于只接受 Foo 类型对象的 fooRule 不成立。- Liskov 原则)
但是我想不出解决这个问题的方法。我如何存储 Rule一个集合中具有不同类型的对象?
请您参考如下方法:
你能做到吗:
[TestFixture]
public class ContraVariance
{
[Test]
public void TestNameTest()
{
var rules = new List<IRule<object>>(); //object is used just for demo here, probably some interface of yours is better
rules.Add(new Rule<A>());
rules.Add(new Rule<B>());
}
}
public class A { }
public class B { }
public class Rule<TEntity> : IRule<TEntity>
{
}
public interface IRule<out T>
{
}
如果不是,我认为你必须有一个非通用的 IRule 或 RuleBase(类) out 关键字 int 接口(interface)意味着 T 仅输出(协变)你可以阅读它 here . 我想这对你的情况来说是个问题,我怀疑这些规则有将 TEntity 作为参数传递的方法。
