कैसे जांचा जाए कि कोई वस्तु C # में अनुक्रमिक है या नहीं


94

मैं यह जांचने का एक आसान तरीका ढूंढ रहा हूं कि क्या C # में कोई ऑब्जेक्ट सीरियल करने योग्य है।

जैसा कि हम जानते हैं कि आप ISIRializable इंटरफ़ेस लागू करके या वर्ग के शीर्ष पर [Serializable] रखकर किसी वस्तु को क्रमबद्ध बनाते हैं ।

मैं जिस चीज की तलाश कर रहा हूं, वह यह जांचने का एक त्वरित तरीका है कि यह विशेषता पाने के लिए कक्षा को प्रतिबिंबित किए बिना। इंटरफेस त्वरित का उपयोग कर एक होगा है बयान।

@ फ़्लर्ड के सुझाव का उपयोग करना यह कोड है जो मैं लेकर आया हूं, चीख वहाँ एक बेहतर तरीका है।

private static bool IsSerializable(T obj)
{
    return ((obj is ISerializable) || (Attribute.IsDefined(typeof (T), typeof (SerializableAttribute))));
}

या इससे भी बेहतर बस वस्तु का प्रकार प्राप्त करें और फिर प्रकार पर IsSerializable संपत्ति का उपयोग करें:

typeof(T).IsSerializable

याद रखें कि यह केवल उस वर्ग को लगता है जिसे हम निपटा रहे हैं यदि वर्ग में अन्य वर्ग हैं जिन्हें आप संभवतः उन सभी को जांचना चाहते हैं या क्रमबद्ध करें और त्रुटियों के लिए प्रतीक्षा करें और जैसा कि @pb ने बताया है।


1
क्षमा करें कि जब obj में कोई क्षेत्र क्रमिक नहीं है, तो मेरा नमूना देखें।
पॉल वैन ब्रेनक

मुझे लगता है कि यह एक बेहतर तरीका है: stackoverflow.com/questions/236599/…
xero

बयान "आप एक वस्तु को सीरियल बनाने योग्य बनाकर या तो ISerializable इंटरफ़ेस लागू कर रहे हैं या [Serializable] वर्ग के शीर्ष पर रखकर" गलत है। किसी वस्तु को क्रमबद्ध होने के लिए, उसकी कक्षा को SerializableAttribute घोषित करना होगा। केवल ISerializable को लागू करने से आपको प्रक्रिया पर अधिक नियंत्रण प्राप्त होता है।
मिशाक्स

जवाबों:


115

आपके पास Typeक्लास नामक एक प्यारी सी संपत्ति है IsSerializable


7
यह आपको सूचित करेगा कि क्या आपकी श्रेणी में सीरियल की विशेषता जुड़ी हुई है।
फातमा

37
उनकी बात यह है कि उस प्रकार के सदस्य क्रमिक नहीं हो सकते हैं, भले ही युक्त प्रकार हो। सही? क्या यह ऐसा नहीं है कि हमें उस ऑब्जेक्ट के सदस्यों में पुनरावर्ती रूप से ड्रिल करना चाहिए और हर एक की जांच करनी चाहिए, अगर यह केवल इसे क्रमबद्ध करने की कोशिश नहीं करता है और देखें कि क्या यह विफल रहता है?
ब्रायन स्वीनी

3
उदाहरण के लिए एक सूची <SomeDTO> IsSerializable सच है, भले ही SomeDTO धारावाहिक नहीं है
शमौन Dowdeswell

43

आपको अनुक्रमिक विशेषता के लिए अनुक्रमित की जा रही वस्तुओं के ग्राफ में सभी प्रकार की जांच करनी होगी। सबसे आसान तरीका है कि वस्तु को क्रमबद्ध करना और अपवाद को पकड़ने की कोशिश करना। (लेकिन यह सबसे साफ समाधान नहीं है)। Type.IsSerializable और serializalbe विशेषता के लिए जाँच ग्राफ को ध्यान में नहीं रखते हैं।

नमूना

[Serializable]
public class A
{
    public B B = new B();
}

public class B
{
   public string a = "b";
}

[Serializable]
public class C
{
    public D D = new D();
}

[Serializable]
public class D
{
    public string d = "D";
}


class Program
{
    static void Main(string[] args)
    {

        var a = typeof(A);

        var aa = new A();

        Console.WriteLine("A: {0}", a.IsSerializable);  // true (WRONG!)

        var c = typeof(C);

        Console.WriteLine("C: {0}", c.IsSerializable); //true

        var form = new BinaryFormatter();
        // throws
        form.Serialize(new MemoryStream(), aa);
    }
}

यदि लागत बहुत अधिक नहीं है, तो मुझे लगता है कि यह दृष्टिकोण सबसे अच्छा है। यह विभिन्न क्रमांकन आवश्यकताओं (बाइनरी, एक्सएमएल) की जांच कर सकता है। इसके अलावा, एक वस्तु में एक सामान्य सदस्य हो सकता है जिसे विरासत में मिले वर्ग प्रकारों के साथ स्वैप किया जा सकता है जो क्रमबद्धता को तोड़ सकता है और रनटाइम में बदल सकता है। बेसकेल्स की सूची (लिस्ट) में सबक्लास से जुड़ी हुई चीजें हो सकती हैं, जो कि सीरियल करने योग्य नहीं है, जहां बेसकलैस और सबक्लासबी सीरियलसेबल हैं।
वोट कॉफ़ी

यह उत्तर यह जाँचने के लिए क्लोनिंग का उपयोग करता है कि क्या क्रमांकन चक्कर लगा सकता है। यह कुछ मामलों में ओवरकिल हो सकता है, हालांकि क्रमांकन कुछ सदस्यों को सेट करने की उम्मीद नहीं की गई थी: stackoverflow.com/questions/236599/…
वोट कॉफ़ी

18

यह एक पुराना प्रश्न है, जिसे .NET 3.5+ के लिए अद्यतन करने की आवश्यकता हो सकती है। यदि DataContract विशेषता का उपयोग करता है तो Type.IsSerializable वास्तव में गलत वापस आ सकता है। यहाँ एक स्निपेट का उपयोग किया गया है, अगर यह बदबू आ रही है, तो मुझे बताएं :)

public static bool IsSerializable(this object obj)
{
    Type t = obj.GetType();

     return  Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable)

}

1
पुराने सवाल और पुराने जवाब लेकिन यह बहुत सच है! Type.IsSerializable केवल एक आंशिक रूप से कार्यात्मक समाधान है। वास्तव में, इन दिनों WCF और DataContracts का उपयोग करने वाले कितने दिए गए हैं, यह वास्तव में एक बहुत ही खराब समाधान है!
Jaxidian

अगर अशक्त के रूप में आता है तो क्या होगा?
N73k

@ N73k एक nullचेक करते हैं और यदि वापस आते हैं true?
फ्रेडएम

9

Type.IsSerializable का उपयोग करें जैसा कि दूसरों ने बताया है।

यह संभवतः प्रतिबिंबित करने और जांचने के प्रयास के लायक नहीं है कि क्या ऑब्जेक्ट ग्राफ में सभी सदस्य क्रमबद्ध हैं।

एक सदस्य को एक क्रमबद्ध प्रकार के रूप में घोषित किया जा सकता है, लेकिन वास्तव में एक व्युत्पन्न प्रकार के रूप में त्वरित किया जा सकता है जो कि अनुक्रमित नहीं है, जैसा कि निम्नलिखित संदर्भ में दिया गया है:

[Serializable]
public class MyClass
{
   public Exception TheException; // serializable
}

public class MyNonSerializableException : Exception
{
...
}

...
MyClass myClass = new MyClass();
myClass.TheException = new MyNonSerializableException();
// myClass now has a non-serializable member

इसलिए, भले ही आप यह निर्धारित करें कि आपके प्रकार का एक विशिष्ट उदाहरण क्रमबद्ध है, आप सामान्य रूप से यह सुनिश्चित नहीं कर सकते कि यह सभी उदाहरणों के लिए सही होगा।


6
Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute));

संभवतः प्रतिबिंब पानी के नीचे शामिल है, लेकिन सबसे सरल तरीका है?


5

यहां एक 3.5 भिन्नता है जो इसे विस्तार विधि का उपयोग करके सभी वर्गों के लिए उपलब्ध कराती है।

public static bool IsSerializable(this object obj)
{
    if (obj is ISerializable)
        return true;
    return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute));
}

2

मैंने इस सवाल का जवाब और यहाँ उत्तर लिया और इसे संशोधित किया ताकि आपको उन प्रकारों की एक सूची प्राप्त हो जो क्रमबद्ध नहीं हैं। इस तरह आप आसानी से जान सकते हैं कि किन लोगों को चिह्नित करना है।

    private static void NonSerializableTypesOfParentType(Type type, List<string> nonSerializableTypes)
    {
        // base case
        if (type.IsValueType || type == typeof(string)) return;

        if (!IsSerializable(type))
            nonSerializableTypes.Add(type.Name);

        foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (propertyInfo.PropertyType.IsGenericType)
            {
                foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments())
                {
                    if (genericArgument == type) continue; // base case for circularly referenced properties
                    NonSerializableTypesOfParentType(genericArgument, nonSerializableTypes);
                }
            }
            else if (propertyInfo.GetType() != type) // base case for circularly referenced properties
                NonSerializableTypesOfParentType(propertyInfo.PropertyType, nonSerializableTypes);
        }
    }

    private static bool IsSerializable(Type type)
    {
        return (Attribute.IsDefined(type, typeof(SerializableAttribute)));
        //return ((type is ISerializable) || (Attribute.IsDefined(type, typeof(SerializableAttribute))));
    }

और फिर आप इसे कहते हैं ...

    List<string> nonSerializableTypes = new List<string>();
    NonSerializableTypesOfParentType(aType, nonSerializableTypes);

जब यह चलता है, तो nonSerializableTypes की सूची होगी। खाली सूची में पुनरावर्ती पद्धति में पास करने की तुलना में ऐसा करने का एक बेहतर तरीका हो सकता है। किसी ने मुझे सही किया तो।


0

अपवाद वस्तु क्रमिक हो सकती है, लेकिन एक अन्य अपवाद का उपयोग करना जो नहीं है। यह वही है जो मैंने अभी WCF System.ServiceModel.FaultException के साथ किया था: FaultException क्रमबद्ध है, लेकिन ExceptionDetail नहीं है!

इसलिए मैं निम्नलिखित का उपयोग कर रहा हूं:

// Check if the exception is serializable and also the specific ones if generic
var exceptionType = ex.GetType();
var allSerializable = exceptionType.IsSerializable;
if (exceptionType.IsGenericType)
    {
        Type[] typeArguments = exceptionType.GetGenericArguments();
        allSerializable = typeArguments.Aggregate(allSerializable, (current, tParam) => current & tParam.IsSerializable);
    }
 if (!allSerializable)
    {
        // Create a new Exception for not serializable exceptions!
        ex = new Exception(ex.Message);
    }

0

मेरा समाधान, VB.NET में:

वस्तुओं के लिए:

''' <summary>
''' Determines whether an object can be serialized.
''' </summary>
''' <param name="Object">The object.</param>
''' <returns><c>true</c> if object can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsObjectSerializable(ByVal [Object] As Object,
                                      Optional ByVal SerializationFormat As SerializationFormat =
                                                                            SerializationFormat.Xml) As Boolean

    Dim Serializer As Object

    Using fs As New IO.MemoryStream

        Select Case SerializationFormat

            Case Data.SerializationFormat.Binary
                Serializer = New Runtime.Serialization.Formatters.Binary.BinaryFormatter()

            Case Data.SerializationFormat.Xml
                Serializer = New Xml.Serialization.XmlSerializer([Object].GetType)

            Case Else
                Throw New ArgumentException("Invalid SerializationFormat", SerializationFormat)

        End Select

        Try
            Serializer.Serialize(fs, [Object])
            Return True

        Catch ex As InvalidOperationException
            Return False

        End Try

    End Using ' fs As New MemoryStream

End Function

प्रकार के लिए:

''' <summary>
''' Determines whether a Type can be serialized.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsTypeSerializable(Of T)() As Boolean

    Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute))

End Function

''' <summary>
''' Determines whether a Type can be serialized.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="Type">The Type.</param>
''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns>
Private Function IsTypeSerializable(Of T)(ByVal Type As T) As Boolean

    Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute))

End Function
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.