1

xml メッセージを受信し、それを別の形式に変換して送信します。メッセージは約 40 行から 600 行以上の xml まであり、平均すると約 100 行です。1 秒間に複数のメッセージを受信できますが、混雑時には平均して 1 分間に 15 ~ 20 通程度です。

xml は既存のアプリケーションに新しい情報を提供するため、出力 xml の構造を模倣するクラスを作成しました。このオブジェクトは、変更された項目のみを含む出力 xml を作成し、入力用語を消費アプリケーションが理解できる言語に変換します。私が理解するのが難しいのは、着信 xml をオブジェクトに簡単にマップする方法です。

着信 xml は、各ノードの形式を決定するいくつかの異なるテンプレートを使用します。ノードの名前が n の場合、オブジェクト m に移動する必要があることを判断できるマップを作成しようとしています。以下は、私がやろうとしていることの簡単な例です。

メッセージ 1

<Incoming>
    <Name>Bob</Name>
    <City>Seattle</City>
    <Hobby>Fishing</Hobby>
</Incoming>

メッセージ 2

<Incoming>
    <Name>Bob</Name>
    <Employment>
        <JobTitle>Sales</JobTitle>
        <Manager>Jessica</Manager>
    </Employment>
    <Hobby>Reading</Hobby>
</Incoming>

これは、次のようなオブジェクトになります。

public Customer
{
    public String Name{get; set;}
    public Address CustomerAddress{get;set;}
    public Employer CustomerEmployer{get;set;}
    public List<String> Hobbies{get;set;}
}

public Address
{
    public String StreetAddress{get;set;}
    public String City{get;set;}
    public String State{get;set;}
    public String Zip{get;set;}
}

public Employer
{
    public String Company{get;set;}
    public String Position{get;set;}
    public String Manager{get;set;}
    public Address CompanyAddress{get;set;}
}

長いスイッチ ケースを作成せずに、xml からオブジェクトに情報を取得する最善の方法についてアイデアを持っている人はいますか? 情報量が多い分、処理の時間コストを意識しています。

マッピングを思いつくことを考えました。何かのようなもの

<Name>Customer:Name</Name>
<City>Customer:Address:City</City>

ただし、Hobby のようにリストにあるアイテムをどのようにマップするかという問題があります。マッピングをすばやく消費する方法の問題もあります。私が考えることができる唯一のことは、各オブジェクトがマップの一部を処理してパスを決定することですが、これはコストがかかるように思えます。

異なるレベルでのアドレスの重複についてはそれほど心配していません。このデータは一例です。私の実際のxmlでは、重複はないと思います。

人々の支援やアイデアに感謝します。前もって感謝します。

4

1 に答える 1

2

リフレクションと再帰を使用して、マップを使用してプロパティにアクセスできました。次のようにマップパスを設定しました:

map = new Dictionary<string, string>();
map.Add("Name", "Name");
map.Add("Street", "Address.Address");
map.Add("City", "Address.City");
map.Add("State", "Address.State");
map.Add("Zip", "Address.Zip");
map.Add("Activity", "*Hobbies.Hobby");
map.Add("Years", "*Hobbies.Years");

アスタリスクは、これがリストであり、キーが必要であることを示します。処理中にキーを追加するので、送信するフル パスは "*Hiking.Hobbies.Years" のようなもので、Hiking がキーです。これを処理するメソッドは次のとおりです。

private void SetValue(object source, String path, String value)
{
    if (path.Contains('.'))
    {
        //  If this is not the ending Property, continue recursing
        int index = path.IndexOf('.');
        String property = path.Substring(0, index);

        object nextSource;
        if(property.Contains("*"))
        {
            path = path.Substring(index + 1);
            index = path.IndexOf('.');
            String dictionaryName = path.Substring(0, index);
            property = property.Substring(1);

            IDictionary list = source.GetType().GetProperty(dictionaryName).GetValue(source, null) as IDictionary;
            if (!list.Contains(property))
            {
                Type[] arguments = list.GetType().GetGenericArguments();
                list.Add(property, Activator.CreateInstance(arguments[1]));
            }

            nextSource = list[property];                    
        }
        else
            nextSource = source.GetType().GetProperty(property).GetValue(source, null);

        SetValue(nextSource, path.Substring(index + 1), value);
    }
    else
    {
        PropertyInfo pi = source.GetType().GetProperty(path);
        pi.SetValue(source, Convert.ChangeType(value, pi.PropertyType), null);
    }
}

これが誰かを助けることを願っています。

于 2013-07-16T21:20:19.533 に答える