在不将属性放入基类的情况下无法消除强制转换,但您可以使用策略模式来解耦对象创建(有关如何执行此操作的示例,请参见我的问题和答案here )。该示例展示了如何解耦 switch-case,但您可以使用策略模式执行相同的操作来分析上下文的结果,因此您可以隐藏演员表。
public static class A
{
// please note: some example in related to your question
// and the strategy pattern provided at the link
public static P GetI(int a)
{
if (a == 1)
return new I();
else
return null; // <- this is important for evaluation
}
// can put this method anywhere else, also into another class
public static P GetO(int a)
{
if (a == 2)
return new O();
else
return null; // <- this is important for evaluation
}
public static bool Condition(string pci)
{
return !string.IsNullOrEmpty(pci); // could eval different states, values
}
}
然后可以将 as/is 逻辑划分为单独的方法/类,调用类(例如控制器、客户端)不需要知道所有不同的专业化。以下代码显示了如何创建上下文。有关Strategy 和 Context 类的实现细节,请参阅我的帖子。
var strategyI = new Strategy<int, P>(A.Condition, A.GetI);
var strategyO = new Strategy<int, P>(A.Condition, A.GetO);
var strategies = new List<Strategy<int, P>> {strategyI, strategyO};
var context = new Context<int, P>(strategies.ToArray());
var result = context.Evaluate(1); // should return a new I(), with 2 as param a new O()
// once you get the result you can create a new context to work with the result
var strategyWorkI = new Strategy<P, P>(Condition, WorkWithI);
var stragegiesForWork = new List<Strategy<P, P>> {strategyWorkI} // could be more than one
var workContext = new Context<P, P>(strategiesForWork.ToArray());
var p = workContext.Evaluate(result); // does the right thing, but
// no need to know class I here (only P)
if (p == null)
// seems to be something went wrong, throw? ...
这是演员阵容的脱钩,但此时您仍然需要演员阵容。
public static P WorkWithI(P p)
{
var i = p as I; // I would prefer as instead of is (see boxing/unboxing in .net)
if (i != null)
{
// do what you want with concrete class I in i
}
return i; // <- this is important for Evaluation
}
无论如何......代码中仍然存在带有is / as的点,但它不会影响您的控制器/管理器等(保持代码灵活和可插入,例如通过依赖注入)
...如果您无法理解我的简短描述,我可以提供一个完整的示例。