문제

나는 알림 프레임 워크를 구축하고 있으며, 내가 보내고 싶은 모든 클래스가 도출 할 기본 클래스를 직렬화하고 실시 할 수 있습니다.

문제는 코드가 컴파일된다는 것입니다. 그러나 실제로이 기본 클래스를 직렬화하려고하면 오류가 발생합니다.

System.Runtime.serialization.serializationException : Assembly 'xxx.datacontracts.wqallocationUpdate'유형 'xxx.datacontract, version = 1.0.0.0, culture = neutral, publicKeytoken = null'은 직렬화 가능하지 않습니다.

코드는 다음과 같습니다.

public class WCallUpdate : NotificationData
{
    private string m_from = "";
    [DataMember]
    public string From
    {
        get { return m_from; }
        set { m_from = value; }
    }
    private WCall m_wCall = new WCall();
    [DataMember]
    public WCall Call
    {
        get { return m_wCall; }
        set { m_wCall = value; }
    }
}

그만큼 DataContract 알림은 다음과 같습니다.

/// <summary>
/// Basic class used in the notification service
/// </summary>
[DataContract]
public class NotificationData
{
}

/// <summary>
/// Enum containing all the events used in the application
/// </summary>
[DataContract]
public enum NotificationTypeKey
{
    [EnumMember]
    Default = 0,
    [EnumMember]
    IWorkQueueServiceAttributionAddedEvent = 1,
    [EnumMember]
    IWorkQueueServiceAttributionUpdatedEvent = 2,
    [EnumMember]
    IWorkQueueServiceAttributionRemovedEvent = 3,
}

데이터를 직렬화하는 데 사용되는 코드는 다음과 같습니다.

    #region Create Message
    /// <summary>
    /// Creates a memoryStream from a notificationData
    /// note: we insert also the notificationTypeKey at the beginning of the
    /// stream in order to treat the memoryStream correctly on the client side
    /// </summary>
    /// <param name="notificationTypeKey"></param>
    /// <param name="notificationData"></param>
    /// <returns></returns>
    public MemoryStream CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData)
    {
        MemoryStream stream = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();
        try
        {
            formatter.Serialize(stream, notificationTypeKey);
            formatter.Serialize(stream, notificationData);
        }
        catch (Exception ex)
        {
            Logger.Exception(ex);
        }
        return stream;
    }
    #endregion

메시지를 만들려고 할 때 :

WCallUpdate  m_wCallUpdate = new WCallUpdate();
NotificationTypeKey  m_notificationTypeKey = new NotificationTypeKey.Default;
CreateMessage(notificationTypeKey , wCallUpdate );

다음 오류가 발생했습니다.

System.Runtime.Serialization.SerializationException: Type 'Xxx.DataContracts.WCall' in Assembly 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
   at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   at Xxx.Notification.NotificationMessageFactory.CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData) in Xxx.Notification\NotificationCenter.cs:line 36

직렬화 가능한 플래그를 앞에두면 DataContract 하나는 문제를 해결하지 않습니다.


빠른 답변에 감사드립니다. NotificationData의 코드를 넣는 것을 잊어 버려서 죄송합니다 (메인 게시물에 편집 됨)

나는 성공하지 않고 직렬화 가능한 속성을 두 클래스에 두는 것을 시도했다 :(

#region NotificationData
/// <summary>
/// Basic class used in the notification service
/// </summary>
[Serializable]
[DataContract]
public class NotificationData
{
}
#endregion

그리고

[Serializable]
public class WCallUpdate : NotificationData
{
    private string m_from = "";
    [DataMember]
    public string From
    {
        get { return m_from; }
        set { m_from = value; }
    }
    private WCall m_wCall = new WCall();
    [DataMember]
    public WCall Call
    {
        get { return m_wCall; }
        set { m_wCall = value; }
    }
}

** 편집 : ** Mea Culpa Afterall :) 당신은 둘 다 옳았습니다. 나는 확산하는 것을 잊었다 [Serializable] 모든 어린이 수업에 귀속됩니다. 업데이트 및 컴파일 후에는 더 이상 예외가 없습니다. 정답에 감사드립니다 :)


@Marc Gravel : 실제로 나는 당신이 제안하는 것에 대해 생각하고 다음 DataContractSerializer를 만들었지 만 이것이 효과가 있을지 확실하지 않습니까? 내 수업이 다른 수업을 사용함에 따라? DataContractSerializer의 가장 큰 문제는 직렬화하려는 객체의 유형을 지정해야하며 내 클래스가 다른 클래스를 개인 필드로 사용하므로 문제가 발생할 수 있다는 것입니다.

#region DataContractSerializer
        /// <summary>
        /// Creates a Data Contract Serializer for the provided type. The type must be marked with
        /// the data contract attribute to be serialized successfully.
        /// </summary>
        /// <typeparam name="T">The type to be serialized</typeparam>
        /// <returns>A data contract serializer</returns>
        public static DataContractSerializer CreateDataContractSerializer<T>() where T : class
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            return serializer;
        }
        #endregion
도움이 되었습니까?

해결책

직렬화 가능]을 수업의 맨 위에 놓습니다. 직렬화 가능한 것이 반드시 Afaik을 상속받을 필요는 없습니다. 기본 클래스에 [직렬화 가능]이 있더라도 여전히 후손 클래스에서도 필요합니다.

다른 팁

나는 당신이 왜 사용하고 있는지 매우 혼란 스럽습니다 BinaryFormatter 데이터 계약으로. 사용하는 것이 정상입니다 DataContractSerializer 여기 ... 논리는 사용과 유사합니다 [Serializable], 당신이 필요합니다 [DataContract], 그리고 그것은 지명 된 것을 연속화합니다 ([DataMember]) 필드가 아닌 회원 BinaryFormatter 와 일하다.

실제로 여러 가지 이유로 (Brittleness와 같은) 전환을 제안합니다 DataContractSerializer, 특히 그것은 당신의 의도 인 것 같습니다. 또는보다 컴팩트 한 바이너리 형태를 원한다면 protobuf-net 유용 할 수 있습니다 (플러스는 플랫폼 간에도 휴대 할 수 있습니다).

따로 - 당신은 필요하지 않습니다 [DataContract] ~에 enumS- 해를 끼치 지 않지만 많이하지 않습니다.

클래스를 직렬화 가능한 속성으로 표시하거나 MarshalbyRefobject에서 파생 된 상태로 표시하십시오.

NotificationData에서 파생됩니다. 그러면 직렬화 가능합니까?

또한이 점을 확인하십시오. 직렬화 가능한 데이터 클래스가 어셈블리에 넣을 때 Visual Studio에서 프로젝트 또는 파일 참조를 확인하여 올바른 것을 얻으십시오.

또한 어셈블리에 서명하여 GAC에 넣으면 GAC의 어셈블리가 올바른지 확인하십시오! 버전 1.0.0.0에서 1.0.0.1 버전의 어셈블리를 업데이트하고 GAC의 기존 교체를 잊어 버렸기 때문에 많은 시간이 많이 걸리는 디버그 세션이 발생했습니다. GAC의 어셈블리는 현지 어셈블리 이전에로드되며 명심하십시오. 그리고 ... 이진 형식은 어셈블리 버전과 매우 엄격합니다.

나는 이것을 달성하기 위해 클래스 XList를 만들었습니다.

AA D1=new AA(); //Derived type
BB D2=new BB(); //Derived type 
CC D3=new CC(); //Derived type 
X D4=new X(); //Base Class 

XList<X> AllData=new XList<X>(); 
AllData.Add(D1); 
AllData.Add(D2); 
AllData.Add(D3); 
AllData.Add(D4); 
// ----------------------------------- 
AllData.Save(@"C:\Temp\Demo.xml"); 
// ----------------------------------- 
// Retrieve data from XML file 
// ----------------------------------- 
XList<X> AllData=new XList<X>(); 
AllData.Open(@"C:\Temp\Demo.xml"); 
// -----------------------------------

자세한 내용은 찾을 수 있습니다 여기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top