نوع C# العام في فئة أساسية
-
18-09-2019 - |
سؤال
أنا أكتب نظامًا يحتوي على مجموعة من المخازن المؤقتة للبروتوكول (باستخدام 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);
والفرق الرئيسي هنا هو كيفية كتابة المتغيرات.