Class Serialize 시 Event 처리

Class Serialize 시 Event 처리

직렬화(Serialization)는 객체를 저장 또는 전송하기 위해 바이트 스트림으로 변환하는 과정입니다. 그러나 C#에서 이벤트는 기본적으로 직렬화되지 않습니다. 이는 이벤트가 델리게이트 필드를 통해 구현되기 때문입니다. 이벤트 필드에 등록된 델리게이트(콜백 메서드)는 일반적으로 비직렬화 가능한 컴포넌트에 대한 참조를 포함하기 때문에 문제가 발생합니다. 이 문제를 해결하려면 몇 가지 방법이 있습니다:

방법 1: 이벤트 필드 직렬화에서 제외하기

이벤트 필드를 직렬화에서 제외하려면 NonSerialized 특성을 사용하여 이벤트 필드를 직렬화되지 않도록 지정할 수 있습니다. 예를 들어:

[Serializable]
public class Threshold
{
    [field: NonSerialized]
    public event EventHandler ThresholdChangeEvent;
    [SortedCategory("Threshold", 0)]
    [SortedDisplayName("Interval", 0)]
    [Description("This is a cycle (sec) to check the system.")]
    [XmlAttribute]
    public int TimeInterval { get; set; } = 10;
    internal int Interval => TimeInterval * 1000;
    private float _cpu = 80;
    [SortedCategory("Threshold", 0)]
    [SortedDisplayName("CPU", 1)]
    [Description("Alarm when cpu usage (%) is greater than the set value")]
    [XmlAttribute]
    public float Cpu
    {
        get => _cpu;
        set
        {
            if (_cpu != value)
            {
                _cpu = value;
                ThresholdChangeEvent?.Invoke(this, EventArgs.Empty);
            }
        }
    }
}

위의 코드에서는 [field: NonSerialized] 특성을 사용하여 ThresholdChangeEvent 이벤트 필드를 직렬화에서 제외합니다.

방법 2: 이벤트 다시 연결하기

객체를 직렬화하고 다시 역직렬화한 후에 이벤트를 다시 연결하는 방법도 있습니다. 객체의 역직렬화 후 이벤트를 수동으로 다시 연결해야 합니다. 이를 위해 객체가 역직렬화될 때 이벤트를 다시 연결하는 초기화 메서드를 작성할 수 있습니다.

방법 3: ISerializable 인터페이스 사용

더 복잡한 시나리오에서는 ISerializable 인터페이스를 구현하여 커스텀 직렬화 논리를 제공할 수 있습니다. 이 방법은 객체의 직렬화 및 역직렬화 과정을 완벽하게 제어할 수 있게 합니다. 그러나 이는 복잡도가 높아질 수 있습니다. 위의 예제들 중 하나를 사용하면 이벤트가 포함된 클래스를 안전하게 직렬화할 수 있습니다. 대부분의 경우 첫 번째 방법인 NonSerialized 특성을 사용하는 것이 가장 간단하고 효과적입니다.