سؤال

أنا أكتب نظامًا يحتوي على مجموعة من المخازن المؤقتة للبروتوكول (باستخدام protobuf-net)، أريد تحديد شيء مثل هذا في فئة مجردة ورثوها جميعًا:

public byte[] GetBytes()

ومع ذلك، يتطلب serealiser المخزن المؤقت للبروتوكول وسيطة نوع، هل هناك طريقة فعالة للحصول على نوع الفئة الموروثة؟

مثال:

public byte[] GetBytes()
    {
        using (MemoryStream stream = new MemoryStream())
        {
            Serializer.Serialize<T /* what goes here? */>(stream, this);
            return stream.ToArray();
        }
    }
هل كانت مفيدة؟

المحلول

فقط أكتب "T" أليس كذلك؟

ثم في إعلان صفك:

public class M<T>

?

-- يحرر

ثم عندما ترثها:

public class Foo : M<Apple>

نصائح أخرى

يمكنك القيام بذلك عن طريق التفكير، ولكن protobuf-net قامت بذلك نيابةً عنك.

فقط قم بتغيير مكالمتك إلى:

Serializer.NonGeneric.Serialize(stream, this /* Takes an object here */);

يعمل هذا عن طريق بناء الطريقة العامة في وقت التشغيل عبر الانعكاس.لمزيد من التفاصيل، تحقق من الكود (الطريقة الثانية هنا).

تحديد الفئة الأساسية الخاصة بك كما BaseClass<T> ثم تستبدل الفئات المشتقة T بنوع التسلسل DerivedClass<SerializerType>.

يمكنك أيضًا تحديد القيود على وسيطة النوع، على سبيل المثال.

BaseClass<T> where T : SerializerBase

هنا هو وصف لأنواع القيود التي يمكنك تطبيقها.

في الواقع لا تحتاج إلى أي شيء خاص هنا...منذ protobuf-net يحترم الميراث.اذا كنت تمتلك:

[ProtoInclude(typeof(Foo), 20)]
[ProtoInclude(typeof(Bar), 21)]
public abstract class MyBase {
    /* other members */

    public byte[] GetBytes()
    {
        using(MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize<MyBase>(ms, this); // MyBase can be implicit
            return ms.ToArray();
        }
    }
}
[ProtoContract]
class Foo : MyBase { /* snip */ }
[ProtoContract]
class Bar : MyBase { /* snip */ }

ثم أنها سوف تعمل.لتسلسل البيانات، فإنه يبدأ دائمًا بالنوع الأساسي (العقد).;لذلك حتى لو فعلت Serializer.Serialize<Foo>(stream, obj) أول شيء ستفعله هو اكتشاف وجود فئة أساسية تمثل عقدًا والتحول إليها MyBase.أثناء إلغاء التسلسل، سيتم تحديد النوع المشتق (الملموس) الصحيح واستخدامه، حتى تتمكن من استخدامه Deserialize مع MyBase أيضًا، وسوف يقوم ببناء Foo أو Bar اعتمادا على ما كانت البيانات الأصلية.

وبالتالي فإن ما يلي متطابق إلى حد كبير:

Serializer.Serialize<BaseType>(dest, obj);
...
BaseType obj = Serializer.Deserialize<BaseType>(source);

و

Serializer.Serialize<DerivedType>(dest, obj);
...
DerivedType obj = Serializer.Deserialize<DerivedType>(source);

والفرق الرئيسي هنا هو كيفية كتابة المتغيرات.

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