كيفية تحديد نوع معروف من WCF في التكوين الذي هو عام؟

StackOverflow https://stackoverflow.com/questions/976811

سؤال

لدي نوع، دعنا نسميها Data<TKey>. وبعد لدي أيضا عقد خدمة WCF يقبل نوعا (يتيح الاتصال به Wrapper) مع خاصية من النوع Object (لأسباب لن أذهب إلى ذلك، فهذا غير اختياري).

[DataContract]
public class Data<TKey> { ... }

[DataContract]
public class Wrapper
{
    [DataMember]
    public object DataItem { get; set; }
}

الآن أنا أرسل فئتين IntData و LongData:

[DataContract]
public class IntData : Data<int> { /*empty*/ }

[DataContract]
public class LongData : Data<long> { /*empty*/ }

كلاهما تم تكوينه في ملف تكوين الأنواع المعروفة. يشبه التكوين شيئا مثل هذا:

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <knownType type="IntData, MyAssembly"/>
          <knownType type="LongData, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

في هذه المرحلة، كل شيء يعمل بشكل جيد.

لكنني على وشك إضافة نوع ثالث ولا أحب وجود فئات .NET غير ضرورية IntData و LongData. وبعد أنها موجودة فقط لأن ...

أنا لا أعرف كيفية تحديد أنواع عامة في تكوين WCF!

أريد أن أفعل شيئا مثل هذا، ولكن لا أعرف بناء الجملة الدقيق.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is wrong -->
          <knownType type="Data{System.Int32}, MyAssembly"/>
          <knownType type="Data{System.Int64}, MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

ما هو بناء الجملة الصحيح لهذا؟

(لاحظ أيضا أنني لا أستطيع وضع [KnownType(...)] سمات على Wrapper لأنها ليست بلدي النوع. التكوين يبدو أن الطريقة الوحيدة.)

تعديل

@ إجابة باريتا عملت بشكل جيد. ملاحظة ولكن في البداية تلقيت هذا الخطأ:

اكتب "myassembly.data`1 [system.int64] لا يمكن إضافته إلى قائمة الأنواع المعروفة منذ نوع آخر "myassembly.data`1 [system.int32] مع نفس اسم عقد البيانات "http://www.mycompany.com/myassembly:data."موجود بالفعل.

لم أذكر ذلك في السؤال الأصلي، لكن النوع الخاص بي يحتوي على اسم عقد بيانات صريح. شيء من هذا القبيل:

[DataContract(Name = "Data")]
public class Data<TKey> { ... }

حدث الخطأ أعلاه حتى أزلت Name قيمة العقار من السمة. نأمل أن يساعد شخصا آخر أيضا. أنا لا أعرف الشكل الذي يعمل في هذا السيناريو. هذه لم:

[DataContract(Name = "Data\`1")]
[DataContract(Name = "Data{TKey}")]

أي شخص يعرف كيفية القيام بذلك؟

تحرير 2.

شكرا مرة أخرى إلى baretta الذي أشار إلى أن بناء الجملة الصحيح في الواقع:

[DataContract(Name = "Data{0}")]
هل كانت مفيدة؟

المحلول

النوع العام هو مثيل من سلسلة، إذا اتبعت السلسلة هذا النمط:اسم الفصل متبوعا بحرف "` "، متبوعا بعدد معلمات النوع (في هذه الحالة هو 1)، متبوعا بمعلمات النوع المرفقة داخل" [] "، واستخدام الفاصلة كفاصل فاصل المعلمة.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Wrapper, TheirAssembly">
          <!-- this syntax is all good -->
          <knownType type="Data`1[System.Int32], MyAssembly"/>
          <knownType type="Data`1[System.Int64], MyAssembly"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

تحرير: قد أضيف أيضا، أنه في حالة تحديد معلومات التجميع لمعلمات النوع (ALTHOUG أنها ليست هي الحال بالنسبة للأشياء في mscorlib)، يتم استخدامها بعد ذلك [].

<knownType type="Data`1[[System.Int32, mscorlib]], MyAssembly"/>

تحرير: يمكنك تخصيص أسماء الأنواع العامة في عقود البيانات، باستخدام نمط تنسيق السلسلة.

[DataContract(Name = "Data{0}")]
public class Data<TKey>
{...}

بشكل افتراضي، الاسم الذي تم إنشاؤه للبياناتu003CInt32> النوع هو شيء مثل "dataofint32hj67ak7y"، حيث "HJ67AK7Y" هو تجزئة تم إنشاؤها من سلسلة "urn: افتراضي"، أو مساحة اسم صفك، إذا كان لديك أي. ولكن "البيانات {0}" من شأنها أن تعطيه اسم "Dataint32".

أكثر هنا. وبعد إلقاء نظرة على جزء "تخصيص أسماء عقود البيانات لأنواع عامة" جزء أسفل الصفحة.

نصائح أخرى

من عند هنا...

يمكن أيضا تحديد الأنواع المعروفة في التكوين كما هو موضح أدناه.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                    <parameter index="0"/>
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

يتيح التكوين أعلاه أن المعلمة العامة للدائرة هي نفس المعلمة العامة لشكل النوع المعلن. يتيح التكوين تعريف نوع المعروف من التعقيد التعسفي. على سبيل المثال، إذا كان هناك حاجة إلى تحديد الدائرة <قاموس <string، T >> كأنواع معروف من الشكل <t> (بالطبع هذا أكاديمي بحت)، فيمكن القيام به على النحو التالي.

<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
         <add type="MyCompany.Library.Shape`1,
              MyAssembly, Version=2.0.0.0, Culture=neutral,
              PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
            <knownType type="MyCompany.Library.Circle`1,
                       MyAssembly, Version=2.0.0.0, Culture=neutral,
                       PublicKeyToken=XXXXXX, processorArchitecture=MSIL">
                   <parameter type="System.Collections.Generic.Dictionary`2">
                      <parameter type="System.String"/>
                      <parameter index="0"/>
                   </parameter>                
            </knownType>
         </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>

لاحظ استخدام عنصر التكوين "المعلمة" باستخدام "النوع" والفهرس ".

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