كيفية إجراء نسخة عميقة من كائن لم يتم وضع علامة على أنه قابل للتسلسل (في C #)؟

أحاول إنشاء مكدس الحافظة في C #. يتم تخزين بيانات الحافظة في كائنات System.Windows.Forms.DataObject . أردت تخزين كل إدخال من الحافظات ( IDataObject ) مباشرة في قائمة عامة. نظرًا للطريقة التي يتم بها تخزين Bitmaps (يبدو أنها) ، أعتقد أنني بحاجة إلى إجراء نسخة عميقة أولاً قبل إضافتها إلى القائمة.

حاولت استخدام التسلسل الثنائي (انظر أدناه) لإنشاء نسخة عميقة ولكن بما أن System.Windows.Forms.DataObject لم يتم وضع علامة عليه كسلسلة من فشل عملية التسلسل. أيه أفكار؟

public IDataObject GetClipboardData()
{
    MemoryStream memoryStream = new MemoryStream();
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    binaryFormatter.Serialize(memoryStream, Clipboard.GetDataObject());
    memoryStream.Position = 0;
    return (IDataObject) binaryFormatter.Deserialize(memoryStream);
}
3

3 إجابة

كتبت الشفرة أدناه لسؤال آخر وربما يمكن أن تكون مفيدة لك في هذا السيناريو:

    public static class GhettoSerializer
    {
           //you could make this a factory method if your type
           //has a constructor that appeals to you (i.e. default 
           //parameterless constructor)
            public static void Initialize(T instance, IDictionary values)
            {
                    var props = typeof(T).GetProperties();

                   //my approach does nothing to handle rare properties with array indexers
                    var matches = props.Join(
                            values,
                            pi => pi.Name,
                            kvp => kvp.Key,
                            (property, kvp) =>
                                    new {
                                            Set = new Action(property.SetValue), 
                                            kvp.Value
                                    }
                    );

                    foreach (var match in matches)
                            match.Set(instance, match.Value, null);
            }
            public static IDictionary Serialize(T instance) { var props = typeof(T).GetProperties(); var ret = new Dictionary(); foreach (var property in props) { if (!property.CanWrite || !property.CanRead) continue; ret.Add(property.Name, property.GetValue(instance, null)); } return ret; } } 

ومع ذلك ، لا أعتقد أن هذا سيكون الحل النهائي لمشكلتك على الرغم من أنه قد يمنحك مكانًا للبدء.

3
وأضاف
نعم ، إنه خطأ في الشفرة. بدلاً من typeof (T) .GetProperties() ، يجب أن يقول instance.GetType (). GetProperties() . في الواقع ، يمكنني القول أنه يجب استخدام الحقول بدلاً من الخصائص ، ولكن هذا خيار تصميم.
وأضاف المؤلف Timwi, مصدر
شكرا لأخذ لقطة في هذا (نقطة لتسمية تسمية الطبقة كذلك). لسوء الحظ IDataObject لا يحتوي على خصائص. يتم "استخراج البيانات" باستخدام طرق ، بحيث تقوم الشفرة الموجودة أعلاه بإرجاع قاموس فارغ.
وأضاف المؤلف cgray4, مصدر

Copy of my answer to: difference between DataContract attribute and Serializable attribute in .net

يناسب جوابي هنا بشكل أفضل من ذلك ، على الرغم من أن السؤال أعلاه ينتهي بـ:

"... أو ربما طريقة مختلفة لإنشاء عقدة عميقة؟"

لقد قمت بإجراء بعض التفتيش على بنية كائن من خلال الانعكاس للعثور على جميع التجميعات اللازمة لإزالة التسلسل وتسلسلها جنبًا إلى جنب لإقلاعها.

مع قليل من العمل يمكن للمرء بناء أسلوب مماثل للنسخ العميق. تحتاج في الأساس إلى طريقة متكررة تحمل على طول القاموس للكشف عن المراجع الدائرية. داخل الطريقة تقوم بفحص جميع الحقول حول مثل هذا:

private void InspectRecursively(object input,
    Dictionary processedObjects)
{
  if ((input != null) && !processedObjects.ContainsKey(input))
  {
    processedObjects.Add(input, true);

    List fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); foreach (FieldInfo field in fields) { object nextInput = field.GetValue(input); if (nextInput is System.Collections.IEnumerable) { System.Collections.IEnumerator enumerator = (nextInput as System.Collections.IEnumerable).GetEnumerator(); while (enumerator.MoveNext()) { InspectRecursively(enumerator.Current, processedObjects); } } else { InspectRecursively(nextInput, processedObjects); } } } } 

To get it working you need to add an output object and something like System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type) to create the most shallowest copy (even without copying references) of each field's value. Finally you can set each field with something like field.SetValue(input, output)

ومع ذلك ، لا يدعم هذا التطبيق معالجات الأحداث المسجلة ، وهي _ un _supported by deserializing أيضًا. بالإضافة إلى ذلك ، سيتم كسر كل كائن في التسلسل الهرمي ، إذا كان منشئه 'class يحتاج إلى تهيئة أي شيء ولكن إعداد كافة الحقول. النقطة الأخيرة تعمل فقط مع التسلسل ، إذا كان للصف تطبيق خاص به ، على سبيل المثال ، تم وضع علامة [OnDeserialized] ، على طريقة iserializable ، ....

0
وأضاف

ابحث عن أحواض Serializable والعثور على الأشياء حول مساعدين التسلسل. يمكنك التفاف الصورة النقطية في رمز التسلسل الخاص بك يتكامل مع إطار .net.

0
وأضاف