2

この質問は、キャストの「is」「as」と、 CA1800 PostSharpルールに関するものです。私が考えた解決策が可能な限り最善のものなのか、それとも私には見えない問題があるのか​​ を知りたい.

私はこのコードを持っています (OriginaL Code という名前で、関連する最小限に縮小されています)。関数 ValidateSubscriptionLicenceProducts は、SubscriptionLicence (Standard、Credit、TimeLimited の 3 つのタイプの可能性があります) の検証を試みます。

PostSharp は CA1800:DoNotCastUnnecessarily について文句を言います。その理由は、同じオブジェクトを同じ型に 2 回キャストしているためです。このコードは、最高の場合で 2 回 (StandardLicence の場合)、最悪の場合で 4 回 (TimeLimited Licence の場合) キャストします。ここではパフォーマンスに大きな影響がないため、ルールを無効にすることが可能であることはわかっていますが (これが私の最初のアプローチでした)、最善のアプローチを試みています。

 //Version Original Code
  //Min 2 casts, max 4 casts
  //PostSharp Complains about CA1800:DoNotCastUnnecessarily
  private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence)
        {
   if (licence is StandardSubscriptionLicence)
            {               
                // All products must have the same products purchased
                List<StandardSubscriptionLicenceProduct> standardProducts = ((StandardSubscriptionLicence)licence).SubscribedProducts;
                //Do whatever
            }
            else if (licence is CreditSubscriptionLicence)
            {               
                // All products must have a valid Credit entitlement & Credit interval
                List<CreditSubscriptionLicenceProduct> creditProducts = ((CreditSubscriptionLicence)licence).SubscribedProducts;
                //Do whatever
            }
            else if (licence is TimeLimitedSubscriptionLicence)
            {                
                // All products must have a valid Time entitlement
                // All products must have a valid Credit entitlement & Credit interval
                List<TimeLimitedSubscriptionLicenceProduct> creditProducts = ((TimeLimitedSubscriptionLicence)licence).SubscribedProducts;
                //Do whatever 
            }
            else
                throw new InvalidSubscriptionLicenceException("Invalid Licence type");

   //More code...


        }

これは"as"を使用した改良版です。CA1800 について文句を言う必要はありませんが、問題は常に 3 回キャストすることです (将来的に 30 種類または 40 種類のライセンスがある場合、パフォーマンスが低下する可能性があります)。

    //Version Improve 1
  //Minimum 3 casts, maximum 3 casts
  private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence)
        {
      StandardSubscriptionLicence standardLicence = Slicence as StandardSubscriptionLicence;
            CreditSubscriptionLicence creditLicence = Clicence as CreditSubscriptionLicence;
            TimeLimitedSubscriptionLicence timeLicence = Tlicence as TimeLimitedSubscriptionLicence;

   if (Slicence == null)
            {               
                // All products must have the same products purchased
                List<StandardSubscriptionLicenceProduct> standardProducts = Slicence.SubscribedProducts;
                //Do whatever
            }
            else if (Clicence == null)
            {               
                // All products must have a valid Credit entitlement & Credit interval
                List<CreditSubscriptionLicenceProduct> creditProducts = Clicence.SubscribedProducts;
                //Do whatever
            }
            else if (Tlicence == null)
            {                
                // All products must have a valid Time entitlement
                // All products must have a valid Credit entitlement & Credit interval
                List<TimeLimitedSubscriptionLicenceProduct> creditProducts = Tlicence.SubscribedProducts;
                //Do whatever 
            }
            else
                throw new InvalidSubscriptionLicenceException("Invalid Licence type");

   //More code...
        }

しかし、後で私は最高のものを考えました。これは私が使用している最終バージョンです。

    //Version Improve 2
// Min 1 cast, Max 3 Casts
// Do not complain about CA1800:DoNotCastUnnecessarily
private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence)
        {
            StandardSubscriptionLicence standardLicence = null;
            CreditSubscriptionLicence creditLicence = null;
            TimeLimitedSubscriptionLicence timeLicence = null;

            if (StandardSubscriptionLicence.TryParse(licence, out standardLicence))
            {
                // All products must have the same products purchased
                List<StandardSubscriptionLicenceProduct> standardProducts = standardLicence.SubscribedProducts;
    //Do whatever
            }
            else if (CreditSubscriptionLicence.TryParse(licence, out creditLicence))
            {
                // All products must have a valid Credit entitlement & Credit interval
                List<CreditSubscriptionLicenceProduct> creditProducts = creditLicence.SubscribedProducts;
                //Do whatever
            }
            else if (TimeLimitedSubscriptionLicence.TryParse(licence, out timeLicence))
            {
                // All products must have a valid Time entitlement
                List<TimeLimitedSubscriptionLicenceProduct> timeProducts = timeLicence.SubscribedProducts;
                //Do whatever
            }
            else
                throw new InvalidSubscriptionLicenceException("Invalid Licence type");

            //More code...

        }


    //Example of TryParse in CreditSubscriptionLicence
  public static bool TryParse(SubscriptionLicence baseLicence, out CreditSubscriptionLicence creditLicence)
        {
            creditLicence = baseLicence as CreditSubscriptionLicence;
            if (creditLicence != null)
                return true;
            else
                return false;
        }

クラス StandardSubscriptionLicence、CreditSubscriptionLicence、および TimeLimitedSubscriptionLicence を変更して、「tryparse」メソッドを使用する必要があります (以下のコードにコピーされています)。このバージョンでは、最低でも 1 回のみ、最大 3 回までキャストできると思います。改善2についてどう思いますか?それを行う最良の方法はありますか?

4

2 に答える 2

4

3 つのコード スニペットのうち、「改善 2」が最適なようです。ただし、キャストの必要性を完全になくす方法でデザインを改善できると思います。

ValidateProductsに呼び出される抽象メソッドを追加し、SubscriptionLicence各子ライセンスがその特定の種類のライセンスに固有のロジックを実装できるようにします。このようにして、ビジネス ロジックをデータとともに配置し、ドメイン モデルの貧血を回避します。

このように、メソッドの実装は次のようになります。

private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence)
{
    if(!licence.ValidateProducts())
        throw new Exception("Failed to validate products");
}

さらに、基本クラスでメソッドを抽象化することにより、各「子ライセンス」を強制してメソッドを実装するため、何もチェックする必要がありません。したがって、ValidateSubscriptionLicenceProducts将来新しい種類のライセンスが追加されても、この方法を変更する必要はありません。

それが理にかなっていることを願っています。

于 2010-04-08T10:44:54.173 に答える
0

PostSharp が文句を言うとは思わない。むしろFxCop。

于 2010-04-08T10:54:02.367 に答える