سؤال

هذا سؤال معقد للغاية فيما يتعلق بكيفية إجراء تسلسل للبيانات عبر استدعاء خدمة الويب، عندما لا تتم كتابة البيانات بقوة.سأحاول أن أضعها على أفضل وجه ممكن.

كائن تخزين العينة:

[Serializable]
public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public List<NameValuePairs> OtherInfo { get; set; }  
}
[Serializable]   
public class NameValuePairs {
  public string Name { get; set; }
  public string Value { get; set; }
}

استخدام العينة:

[WebMethod]
    public List<StorageObject> GetStorageObjects() {
      List<StorageObject> o = new List<StorageObject>() {
        new StorageObject() { 
          Name = "Matthew",
          Birthday = "Jan 1st, 2008", 
          OtherInfo = new List<NameValuePairs>() {
            new NameValuePairs() { Name = "Hobbies", Value = "Programming" },
            new NameValuePairs() { Name = "Website", Value = "Stackoverflow.com" }
          }
        },
        new StorageObject() { 
          Name = "Joe",
          Birthday = "Jan 10th, 2008",
          OtherInfo = new List<NameValuePairs>() { 
            new NameValuePairs() { Name = "Hobbies", Value = "Programming" },
            new NameValuePairs() { Name = "Website", Value = "Stackoverflow.com" }
          }
        }
      };

      return o;
    }

قيمة الإرجاع من خدمة الويب:

<StorageObject>
    <Name>Matthew</Name>
    <Birthday>Jan 1st, 2008</Birthday>
    <OtherInfo>
        <NameValuePairs>
            <Name>Hobbies</Name>
            <Value>Programming</Value>
        </NameValuePairs>
        <NameValuePairs>
            <Name>Website</Name>
            <Value>Stackoverflow.com</Value>
        </NameValuePairs>
    </OtherInfo>
</StorageObject>

ماذا اريد:

<OtherInfo>
    <Hobbies>Programming</Hobbies>
    <Website>Stackoverflow.com</Website>
</OtherInfo>

السبب وأشياء أخرى:

أولاً، أنا آسف لطول المنشور، ولكني أردت تقديم رمز قابل للتكرار أيضًا.

أريده بهذا التنسيق، لأنني أستهلك خدمات الويب من PHP.أريد أن أذهب بسهولة:

// هذا مهم

In PHP => "$Result["StorageObject"]["OtherInfo"]["Hobbies"]".  

إذا كان بالصيغة الأخرى، فلن تكون هناك طريقة بالنسبة لي لتحقيق ذلك على الإطلاق.بالإضافة إلى ذلك، في C#، إذا كنت أستهلك الخدمة، أود أيضًا أن أكون قادرًا على القيام بما يلي:

// هذا مهم

In C# => var m = ServiceResult[0].OtherInfo["Hobbies"];

لسوء الحظ، لست متأكدًا من كيفية تحقيق ذلك.لقد تمكنت من الحصول على الأمر بهذه الطريقة، من خلال إنشاء قاموس مخصص يطبق IXmlSerializer (انظر ستاكوفيرفلوو:قاموس IXmlSerializer)، ومع ذلك، فقد فجر مخطط WSDL خارج الماء.كما أنه معقد للغاية، وقد أدى إلى نتائج مروعة في تطبيق WinFormsTester الخاص بي!

هل هناك أي طريقة لتحقيق ذلك ؟ما نوع الكائنات التي أحتاج إلى إنشائها؟هل هناك أي طريقة للقيام بذلك/بخلاف إنشاء مجموعة مكتوبة بقوة/؟من الواضح ، إذا قمت بكتابتها بقوة مثل هذا:

public class OtherInfo {
  public string Hobbies { get; set; }
  public string FavoriteWebsite { get; set; }
}

ثم سيعمل بشكل مثالي، ولن أواجه أية مشكلات في WSDL، وسأكون قادرًا على الوصول إليه بسهولة من PHP وC# (.OtherInfo.Hobbies).

ومع ذلك، سأفقد تمامًا مغزى NVP، حيث يجب أن أعرف مسبقًا ما هي القائمة، ولن تكون قابلة للتغيير..قل، من قاعدة البيانات.

شكرا لكم جميعا!!آمل أن نتمكن من التوصل إلى نوع من الحل لهذا الأمر.وإليك المتطلبات مرة أخرى:

  1. يجب ألا ينقطع مخطط WSDL
  2. يجب إجراء تسلسل لأزواج قيمة الاسم (NVP's) في تنسيق السمة
  3. يجب أن يكون من السهل الوصول إلى NVP في PHP بالاسم ["الهوايات"]
  4. يجب أن يكون من السهل الوصول إليه في C# (وأن يكون متوافقًا مع منشئ الوكيل الخاص به)
  5. تكون قابلة للتسلسل بسهولة
  6. لا يطلب مني أن أكتب البيانات بقوة

الآن، أنا منفتح /تمامًا/ على الإدخال بطريقة أفضل/مختلفة للقيام بذلك.أقوم بتخزين بعض المعلومات "الثابتة" نسبيًا (مثل الاسم) ومجموعة من البيانات.إذا كانت هناك طريقة أفضل، فأنا أحب أن أسمعها.

هل كانت مفيدة؟

المحلول

هذا يشبه الخصائص الديناميكية للكائن.C# ليست لغة ديناميكية تمامًا على عكس جافا سكريبت أو ربما يمكن لـ PHP تحليل خصائص الكائن بسرعة.الطريقتان التاليتان هما ما يمكنني التفكير فيه.والثاني قد يناسب متطلباتك.

طريقة القبلة

يبقيه طريقة غبية بسيطة

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public List<string> OtherInfo { get; set; }  
}

يمكن أن يكون لديك أزواج قيمة اسمية مفصولة بـ '|'

OtherInfo = {"Hobbies|Programming", "Website|Stackoverflow.com"}

النماذج المتسلسلة

<StorageObject>
    <Name>Matthew</Name>
    <Birthday>Jan 1st, 2008</Birthday>
    <OtherInfo>
        <string>Hobbies|Programming</string>
        <string>Website|Stackoverflow.com</string>
    </OtherInfo>
</StorageObject>

الطريقة الديناميكية في C#

اجعل جزء زوج قيمة الاسم يصبح عنصر XML حتى تتمكن من إنشائه ديناميكيًا.

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  public XElement OtherInfo { get; set; } // XmlElement for dot net 2
}

You can easily build up OtherInfo object as element centric e.g.

XElement OtherInfo = new XElement("OtherInfo");
OtherInfo.Add( ..Hobbies xelement & text value..);
OtherInfo.Add( ..WebSite xelement & text value..);

سيكون النموذج المتسلسل

<OtherInfo>
    <Hobbies>Programming</Hobbies>
    <Website>Stackoverflow.com</Website>
</OtherInfo>

أو بنائها على أنها سمة تتمحور حولها

XElement OtherInfo = new XElement("OtherInfo");
OtherInfo.Add( ..nvp xattribute Hobbies & value..);
OtherInfo.Add( ..nvp xattribute WebSite & value..);

<OtherInfo>
    <nvp n="Hobbies" v="Programming" />
    <nvp n="Website" v="Stackoverflow.com" />
</OtherInfo>

لأي لغة ديناميكية، يمكنها الوصول إلى الخصائص مباشرة.بالنسبة للباقي، يمكنهم الوصول إلى القيمة عن طريق قراءة ملف XML.قراءة XML مدعومة بشكل جيد من قبل معظم إطار العمل.

نصائح أخرى

هذا ما استقرت عليه.

هيكل الفصل:

public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }
  [XmlAnyElement("Info")]  // this prevents double-nodes in the XML
  public XElement OtherInfo { get; set; }
}

الاستخدام:

StorageObject o = new StorageObject();
o.OtherInfo.Add(new XElement("Hobbies","Programming");
o.OtherInfo.Add(new XElement("Website","Stackoverflow.com");

انتاج:

<Info>
  <Hobbies>Programming</Hobbies>
  <Website>Stackoverflow.com</Website>
</Info>

أود أن أشكر الجميع على مساعدتهم، وأنا أقدر حقًا المساعدة والأفكار.

كنظرة مختلفة تمامًا لهذا الأمر، لماذا لا نفكر في القيام بذلك بشكل مختلف تمامًا.لديك طريقة خدمة ويب واحدة لإرجاع كائن التخزين المتسلسل، مطروحًا منه OtherInfo وطريقة أخرى لإرجاع قائمة الخصائص (المفاتيح) لـ OtherInfo, وثالث لإرجاع قائمة القيم لأي مفتاح.من المؤكد أن الأمر سيستغرق المزيد من الرحلات ذهابًا وإيابًا إلى خدمة الويب إذا كنت تريد جميع البيانات، ولكن الحل سيكون أبسط بكثير وأكثر مرونة.

[Serializable]
public class StorageObject {
  public string Name { get; set; }
  public string Birthday { get; set; }

  [Nonserializable]
  public Dictionary<string,List<string>> OtherInfo { get; set; }  
}

[WebMethod]
public List<StorageObject> GetStorageObjects() {
    // returns list of storage objects from persistent storage or cache
}

[WebMethod]
public List<string> GetStorageObjectAttributes( string name )
{
    // find storage object, sObj
    return sObj.Keys.ToList();
}

[WebMethod]
public List<string> GetStorageObjectAtributeValues( sting name, string attribute )
{
    // find storage object, sObj
    return sObj[attribute];
}

قم بإلقاء نظرة على سمة System.Xml.Serialization.XmlSerializerAssemblyAttribute.يتيح لك هذا تحديد مُسلسل مخصص على مستوى الفصل.ستكون قادرًا على نشر أي لغة XML تريدها.

إحدى الطرق السريعة للتعرف على هذه الأمور هي استخدام sgen.exe لإنشاء ملف وإلقاء نظرة خاطفة عليه باستخدام Reflector.

-أويسين

لست متأكدًا من أن هذا سيحل مشكلتك (سيكون في C#، ولكن ربما ليس في PHP)، ولكن حاول استخدام Dictionary<string,List<string>> OtherInfo بدلاً من List<NameValuePairs>.ثم ستكون "الهوايات" و"مواقع الويب" هي مفاتيحك وستكون القيم عبارة عن قائمة الهوايات أو مواقع الويب.لست متأكدًا من كيفية إجراء التسلسل، رغم ذلك.

ستكون قادرًا على الرجوع إلى قوائم الهوايات على النحو التالي:

List<string> hobbies = storageObject.OtherInfo["Hobbies"];

[تحرير] انظر هنا للحصول على قاموس XML عام قابل للتسلسل.هذه الفئة المشتقة هي التي ستحتاج إلى استخدامها بدلاً من القاموس العام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top