1

私は3つのレンタカー会社を持っています。各機関は、XML のデータを必要としますが、次のように異なる形式である必要があります。

代理店 1

<Rental>
<Customer>
<FirstName>test</FirstName>
<LastName>test</LastName>
</Customer>
<Pickup date="07/20/2012"/>
<Dropoff date="07/25/2012"/>
<Deposit cost="100"/>
</Rental>

エージェンシー 2

<Rental>
<Customer>
<FirstName>test</FirstName>
<LastName>test</LastName>
</Customer>
<Pickup>07/20/2012</Pickup>
<Dropoff>07/25/2012</Dropoff>
<Deposit>100</Deposit>
</Rental>

エージェンシー 3

<Rental pickup="07/20/2012" dropoff="07/25/2012" deposit="100">
<Customer>
<FirstName>test</FirstName>
<LastName>test</LastName>
</Customer>
</Rental>

上記からわかるように、3 つすべてに基本的に同じ情報が含まれていますが、必ずしもそうである必要はありません (情報が多かれ少なかれ含まれる場合もあります) が、構造が異なるため、アクセス方法が異なります。最小限のコードを記述しながら、構造の異なる新しいレンタル代理店に適応できるようにするための最善のアプローチは何ですか?

今、私は次のようなことをしています:

public class Agency1
{
SubmitRental()
{
//Parse XML for Agency 1
}

//Other methods for agency 1
}

public class Agency2
{
SubmitRental()
{
//Parse XML for Agency 2
}

 //Other methods for agency 2
}

public class Agency3
{
SubmitRental()
{
//Parse XML for Agency 3
}

//Other methods for agency 3
}

上記のクラスには同じメソッドが含まれていますが、実装方法が異なります。一部のクラスに含まれるメソッドやプロパティなどがありますが、他のクラスには含まれていません。インターフェイスはこれにアプローチする最良の方法ですか? もしそうなら、すべてをインターフェイスにする必要がありますか?

上記の XML サンプルでは、​​データは同じでしたが、形式が異なっていたため、すべての異なる形式を一連の共通クラスにマッピングすることを思いついた人もいましたが、形式が異なるだけでなく、しかし、データも異なりますか?

4

6 に答える 6

4

通常、次のようなデータ表現から解析を分離します。

public class Rental
{
    public string CustomerFirstName { get; set; }
    public DateTime Pickup { get; set; }
    // ... etc ...
}

そして、一連のデータ パーサー:

public interface IAgencyRentalParser
{
    XmlDocument ToXml(Rental rental);
    Rental FromXml(XmlDocument xml);
}

public class Agency1RentalParser : IAgencyRentalParser { ... }

public class Agency2RentalParser : IAgencyRentalParser { ... }

public class Agency3RentalParser : IAgencyRentalParser { ... }

また、使用するパーサーを決定するためのその他のメカニズムもあります。適切なパーサーを返すファクトリ パターンのように...

public class AgencyRentalParserFactory
{
    public IAgencyRentalParser GetParserFor(XmlDocument xml)
    {
        // create and return one of the parsers...
    }
}
于 2012-07-16T19:39:44.067 に答える
1

継承とポリモーフィズム

public class Agency
{
    public virtual void SubmitRental()
    {
        //can leave empty, or provide default behavior
    }

    // methods and properties/fields common to all Agencies.  
}

public class Agency1 : Agency
{
    public override void SubmitRental()
    {
        //insert submit logic here
    }
    //methods and properties/fields specific to Agency1
}

それらが完全に異なる方法で実装されている場合は、インターフェイスを使用できます

http://msdn.microsoft.com/en-us/library/ms173156.aspx

于 2012-07-16T19:36:04.413 に答える
0

すべての機関に共通のすべての情報と、仮想としてマークされたすべてのメソッドを保持する 1 つの基本抽象クラスを作成するだけです。すべての機関に具体的なクラスを作成するよりも。

public abstract class AgencyBase
{
    private string _customer;
    // other fields that every agency have.

    public abstract void SubmitRental();

//Other methods for agency
}

public class Agency1 : AgencyBase
{
    // Agency specific fields.

    public override void SubmitRental()
    {
        // Your implementation.
    }
}
于 2012-07-16T19:39:20.070 に答える
0

考えられるアプローチの 1 つは、共通データを保持する抽象基本クラスのエージェンシーを作成することです。このクラスには、次のような submitRental() という抽象メソッドがあります。

public abstract class Agency {
  public abstract void SubmitRental();

  //Other methods for agency ...
}

public class AgencyOne : Agency {
  public void SubmitRental() {
    // agency one specific code...
  }
}

もう 1 つの方法は、メソッド SubmitRental() を含むインターフェイスを作成することです。代理店ごとに、インターフェイスを継承し、その代理店形式に固有の解析を記述します。

于 2012-07-16T19:40:18.277 に答える
0

私がそれを設計するのであれば、これは私がそれを見る単純な方法です:

1) 代理店オブジェクト:

ID (string to identify 'Agency 1','Agency 2' and so on.)
Customer (Reference to Person Object)
Shipping (Reference to Shipping Object)

SubmitRental メソッド - ID フィールドおよびその他のデータに基づくカスタマイズを含める必要があります

2) 人物オブジェクト:

FirstName
LastName

3) レンタル対象:

Pickup Date
Dropoff Date
Deposit

もちろん、上記の周りに配置できる他のすべてのフィールド/取得/設定メソッドを配置します。

于 2012-07-16T19:40:55.707 に答える
0

BaseAgencyClass、および/または AbstractAgencyClass、および/または IAgency インターフェイスを作成することにより、単一のエージェンシー機能の複数の実装 (これは回避したいことです) を作成する準備をしているだけです。基本クラスと抽象クラスとインターフェイスは、適切に使用すると [非常に] 適切ですが、目的を解決することはできません。代わりに、パーサーで問題を解決してください。

単一のクラス [エージェンシー] を作成し (ソリューションに適している場合はインターフェイスや基本クラスを使用します)、すべてのエージェンシーに対して単一のユニバーサルパーサーを作成します。できるだけ早く、さまざまな形式の XML を共通の Agency オブジェクトに組み込みたいと考えています。XML との違いをエージェンシーの実装に保持しないでください。

パーサー (Agency のメソッド、Agency のコンストラクターに組み込まれているもの、または解析を担当する別のオブジェクトなど) については、XML を動的に解析するだけです。すべての XML は、単なる一連の親/子関係です。XML では常に ROOT 要素が存在するため、いつでも ELEMENT から始めることができます。次にすべき CHILD を見つけるために、まず ELEMENT の ATTRIBUTES を調べます。見つからない場合は、ELEMENT の CHILDREN (ネストされた要素) を調べます。見つからない場合は、ELEMENT の VALUE (ELEMENT 内に保持されているテキスト) を調べます。

この方法で XML を解読し、すべての組み合わせを解析して COMMON Agency オブジェクトにすることができます。コードの重複や複数の実装は必要ありません。幸運を!

編集: 「ユニバーサル パーサー」の記述例を次に示します。これは製品コードではなく、3 つの XML サンプルを使用した簡単で汚い例です。

class Program
{
    static void Main(string[] args)
    {
        IList<XDocument> xmls = new List<XDocument>()
                                    {
                                        XDocument.Load("XMLFile1.xml"),
                                        XDocument.Load("XMLFile2.xml"),
                                        XDocument.Load("XMLFile3.xml")
                                    };
        Agency agency = new Agency();

        foreach (var xml in xmls)
        {
            var rental = new Rental();
            #region Pickup Date
            if (xml.Root.Attribute("pickup") != null)
                rental.Pickup = DateTime.Parse(xml.Root.Attribute("pickup").Value);
            else if (xml.Root.Element("Pickup") != null)
            {
                var pickupElement = xml.Root.Element("Pickup");
                rental.Pickup = DateTime.Parse(pickupElement.Attribute("date") != null ? pickupElement.Attribute("date").Value : pickupElement.Value);
            }
            // else there's no pickup date defined
            #endregion
            agency.rentals.Add(rental);
        }
    }
}

public class Agency
{
    public IList<Rental> rentals = new List<Rental>();
}

public class Rental
{
    public DateTime Pickup;
}

例として、これは「受け取り日」のみを解析し、それを単一の Agency オブジェクトに入力します。「ピックアップ日」が見つかる可能性のある 3 つのシナリオを処理します。前述のように、これは製品コードではないため、より安全で適切な方法で記述します。たとえば、XML では大文字と小文字が区別されるため、解析する前に XML をすべて UPPER または LOWER (可能であれば) に変換することをお勧めします。または、正規表現を使用して、ELEMENT および ATTRIBUTE 名のみを UPPER に変換することもできますが、それが重要な場合は実際の値には影響しません。

あなたが言っているのは、データがまったく未知のXML レイアウトである可能性があるということである場合、これは機能しない可能性があります。しかし、これで少なくとも既知のレイアウトに対処することができ、有効な XML を配置できる方法は非常に多くあります。お役に立てれば!

于 2012-07-16T20:24:52.480 に答える