سؤال

لدي ما يلي:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

عندما أقوم بتشغيل طريقة الحصول على الخطأ التالي:

كان هناك خطأ أثناء محاولة تسلسل المعلمة http://tempuri.org/:GetResult. كانت رسالة innerexception هي "type" pps.core.domainmodel.support.action.actionResult`1 [[pps.core.domainmodel.SportProgram.isportProgram ، pps.core.domainmodel ، الإصدار = 1.0.0 ، الثقافة = محايد ، publictoken = NULL]] "مع اسم عقد البيانات" ActionResultofanyType: http://schemas.datacontract.org/2004/07/pps.core.domainmodel.support.action' غير متوقع. أضف أي أنواع غير معروفة بشكل ثابت لقائمة الأنواع المعروفة - على سبيل المثال ، باستخدام سمة المعروفة المعروفة أو عن طريق إضافتها إلى قائمة الأنواع المعروفة التي تم تمريرها إلى DataContractSerializer. '. يرجى الاطلاع على innerexception لمزيد من التفاصيل.

من هذا الخطأ ، يمكنني أن أرى أنه يمكن حل ActionResult ، لكن لا يمكن حلها servownytype (typeof (ActionResult <SportProgram>)) على واجهة الخدمة الخاصة بي ...

لاحظ أن هذا هو كعب المرجع الذي يتم إنشاؤه يبدو هكذا ، لذلك يمكنني أن أرى أن الأنواع المعروفة يتم عرضها بشكل صحيح:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

لماذا هذا خطأ ؟؟؟؟ لاحظ أنه من خلال خدمة WCF بشكل صحيح ... لكنه يلقي الاستثناء عند إرجاع النتيجة.

أخيرًا ، يبدو ActionResult مثل هذا:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

هتاف أنتوني

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

المحلول

حسنًا ، أعتقد أن هذه حالة أخرى من "عدم تطابق المعاوقة". العالمان منفصلان تمامًا.

في WCF ، يتم تمرير كل ما يتم تمريره من العميل إلى الخادم الرسائل التسلسلية - لا يتم استخدام أي مراجع.

هذا يعني: كل ما تريد أن تتسلسل أسمنت - لا يمكنك المرور حول الواجهات ، لا يمكنك استخدام الأدوية "غير المحللة" - تحتاج إلى تهجئة ذلك. في الأساس ، يجب أن يكون كل ما يتم تمريره من العميل فوق السلك إلى الخادم قابلاً للتعبير في مخطط XML.

هذا له الكثير من الآثار:

  • لا توجد واجهات - لا يمكنك المرور حول واجهات - تحتاج إلى العمل مع أنواع ملموسة
  • لا توجد ميراث "تلقائي" - لا يمكنك فقط تحديد فئة أساسية والتمرير حول الفئات المشتقة بناءً عليها - يجب أن تكون محددة أيضًا (وهذا ما هي سمة ServawnyPe من أجل)
  • لا توجد أجناس تلقائي - مرة أخرى ، تحتاج إلى استخدام أنواع ملموسة بدلاً من ذلك

قد يبدو هذا وكأنه الكثير من القيود - ولكن لأن WCF تستخدم جميع الاتصالات المستندة إلى الرسائل - لا يمكن أن تتعامل مع المراجع والميراث والوحوم الأدوية وما إلى ذلك - تحتاج إلى توضيحها.

لذلك ليس لدي إجابة لك حقًا في حد ذاتها - أعتقد أنك بحاجة إلى إعادة التفكير في استراتيجيتك وتغيير الطريقة التي يقوم بها عميلك وخادمك بتبادل المعلومات عبر WCF.

مارك

ملاحظة: لقد قمت ببعض الأبحاث ، وعلى عكس كل ما أفهمه ، يبدو أن هناك وسيلة لتسلسل أي شيء يعتمد على واجهة و/أو فئة أساسية مجردة عبر السلك ، طالما يمكنك التأكد من أنها دائمًا فقط. صافي على أي من طرفي السلك (أي إنه ليس قابلة للتشغيل مع EG Java).

نرى مدونة آرون سكونارد على NetDatacontractSerializer وآخر مشاركة مدونة و بعد آخر إظهار كيفية استخدام NetDatacontractSerializer ليكون قادرًا على تجاوز أشياء مثل IPerson كمعلمات لطرقك.

نصائح أخرى

هذه واحدة من المشكلات التي أحلها servicestack.net - الإطار الخاص بي المصدر المفتوح .NET و Mono Web Services.

تأثرت كومة الخدمة بشدة Martin Fowlers نقل بيانات نقل البيانات لأنه يتيح لك ببساطة استخدام DTO's لتحديد خدمات الويب الخاصة بك - أي طريقة الخدمية :).

أتجنب هذا القيد المتأصل في WCF من خلال إنشاء WSDL الخاص بي الذي يتصرف كما تتوقع منهم. كفائدة لاستبدال نموذج التكوين المعقد / ServiceContract - تعمل خدمات الويب SOAP أيضًا على Mono - شاهد العرض التوضيحي الحي.

إنه سؤال قديم ، وعلى الرغم من أن الإجابة المقبولة صحيحة تمامًا ، إلا أنني تفوقت على هذا في البحث عن مشكلة مماثلة واعتقدت أنه يمكنني مشاركة تجربتي. غالبًا ما يكون صداعًا ، ولكن من الممكن استخدام الأدوية الجيرية مع واجهات مع WCF. إليك مثالًا عمليًا على تطبيق آخر (مشترك) الذي قمت به:

[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
public interface IService : 
{
    [OperationContract]
    ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);
}

public interface ICollectionWrapper<TModel>
{
    int TotalCount { get; set; }
    IEnumerable<TModel> Items { get; set; }
}

[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
    [DataMember]
    public int TotalCount { get; set; }
    [DataMember]
    public IEnumerable<TModel> Items { get; set; }
}

public class CompanyDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OrganizationDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

المفتاح هنا هو استخدام مزيج من KnownType و ServiceKnownType.

لذلك في حالتك يمكنك أن تفعل شيئًا كهذا:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic.
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

[KnownType(typeof(SportProgram))] // Actual implementation here.
public class ActionResult<T>
{
    // Other stuff here
    T FooModel { get; set; }
}

سيعمل هذا إذا كان لديك عقد مشترك (الوصول إلى واجهة الخدمة الفعلية) واستهلاك العقد مع ChannelFactory<ISportProgramBl>. لا أعرف ما إذا كان يعمل مع مرجع خدمة.

ومع ذلك ، يبدو أن هناك بعض المشكلات في التنفيذ كما هو مذكور هنا:

WCF مع واجهة ونموذج عام

وطرح سؤال مشترك آخر والإجابة عليه هنا:

أنواع الإرجاع العامة مع معاملات نوع الواجهة في WCF

أنت تعيد مجموعة من T. ربما يكون للنظام مشاكل في معرفة ماهية T.

لست متأكدًا مما إذا كان من المقبول إرجاع واجهة بدلاً من نوع.

هل تحدد واجهات في الكائنات وليس أنواعًا ملموسة؟

PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>

يحرر:

ما أقوله هو أن جميع الأنواع الخرسانية التي تمررها في الأدوية (بما في ذلك في الكائن الفرعي عبر الواجهات) التي يتم تمريرها في قائمة الأنواع المعروفة. لقد واجهنا قضايا التسلسل حيث لم تكن جميع الأنواع معروفة.

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