プロパティを基本クラスに入れずにキャストを削除することはできませんが、戦略パターンを使用してオブジェクトの作成を切り離すことができます (これを行う方法の例については、こちらの質問と回答を参照してください)。この例では、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 を含むコードにはまだ Point がありますが、コントローラー/マネージャーなどには影響しません (依存性注入などにより、コードを柔軟でプラグ可能に保ちます)
... 私の簡単な説明が理解できない場合は、完全な例を提供できます。