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
특성을 사용하는 것이 가장 간단하고 효과적입니다.