도입
많은 프로퍼티와 많은 클래스들을 직렬화(Serialization)하려면
직렬화할 멤버 하나당 2줄의 코드를 쓸 필요가 있습니다
또한 코드를 일일이 쓰다보니 잘못 써서 버그가 생길 염려도 있지요
그렇기에 리플렉션을 이용하여 자동화하는 것이 필요합니다
SerializationHelper
using System; 
using System.Linq; 
using System.Reflection; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
namespace CodeGenerater.Example 
{ 
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] 
    public sealed class SerializationTargetAttribute : Attribute 
    { 
    } 
    public static class SerializationHelper 
    { 
        public static void Serialize(object Instance, SerializationInfo Info) 
        { 
            foreach (dynamic each in GetTarget(Instance)) 
                if (each is FieldInfo) 
                    Info.AddValue(each.Name, each.GetValue(Instance), each.FieldType); 
                else if (each is PropertyInfo) 
                    Info.AddValue(each.Name, each.GetValue(Instance), each.PropertyType); 
        } 
        public static void Deserialize(object Instance, SerializationInfo Info) 
        { 
            foreach (dynamic each in GetTarget(Instance)) 
                if (each is FieldInfo) 
                    each.SetValue(Instance, Info.GetValue(each.Name, each.FieldType)); 
                else if (each is PropertyInfo) 
                    each.SetValue(Instance, Info.GetValue(each.Name, each.PropertyType)); 
        } 
        static IEnumerable<MemberInfo> GetTarget(object Instance) 
        { 
            return from q in Instance.GetType().GetMembers(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) 
                   where q.GetCustomAttribute<SerializationTargetAttribute>() != null 
                   select q; 
        } 
    } 
} 
 | cs | 
Serialize, Deserialize 함수에 있는 dynamic 키워드는 4.0버전부터 가능하므로
만약 그 이전의 버전을 사용하고 계실경우 아래와 같이 쓰시면 됩니다
public static void Serialize(object Instance, SerializationInfo Info) 
{ 
    foreach (var each in GetTarget(Instance)) 
        if (each is FieldInfo) 
        { 
            FieldInfo F = each as FieldInfo; 
            Info.AddValue(F.Name, F.GetValue(Instance), F.FieldType); 
        } 
        else if (each is PropertyInfo) 
        { 
            PropertyInfo P = each as PropertyInfo; 
            Info.AddValue(P.Name, P.GetValue(Instance), P.PropertyType); 
        } 
} 
 | cs | 
Example
using System; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 
namespace CodeGenerater.Example 
{ 
    [Serializable] 
    class Program : ISerializable 
    { 
        #region Serializaion 
        public void GetObjectData(SerializationInfo Info, StreamingContext Context) 
        { 
            SerializationHelper.Serialize(this, Info); 
        } 
        Program(SerializationInfo Info, StreamingContext Conmtext) 
        { 
            SerializationHelper.Deserialize(this, Info); 
        } 
        #endregion 
        #region Constructor 
        public Program() 
        { 
        } 
        #endregion 
        #region Field 
        [SerializationTarget] 
        int PrivateField; 
        #endregion 
        #region Property 
        [SerializationTarget] 
        public int PublicProperty 
        { 
            set; 
            get; 
        } 
        [SerializationTarget] 
        public int HalfPublicProperty 
        { 
            private set; 
            get; 
        } 
        [SerializationTarget] 
        int PrivateProperty 
        { 
            set; 
            get; 
        } 
        #endregion 
        #region Method 
        static void Main(string[] args) 
        { 
            var T = new Program(); 
            int R_PrivateProperty, R_HalfPublicProperty, R_PublicProperty, R_PrivateField; 
            #region Initialize 
            Random R = new Random(); 
            T.PrivateProperty = R_PrivateProperty = R.Next(); 
            T.HalfPublicProperty = R_HalfPublicProperty = R.Next(); 
            T.PublicProperty = R_PublicProperty = R.Next(); 
            T.PrivateField = R_PrivateField = R.Next(); 
            #endregion 
            using (MemoryStream Stream = new MemoryStream()) 
            { 
                #region Serialization 
                BinaryFormatter F = new BinaryFormatter(); 
                F.Serialize(Stream, T); 
                #endregion 
                #region Init 
                T = null; 
                Stream.Position = 0; 
                #endregion 
                #region Deserialization 
                T = (Program)F.Deserialize(Stream); 
                #endregion 
                #region Check 
                bool TestSuccess = 
                    T.PrivateProperty == R_PrivateProperty && 
                    T.HalfPublicProperty == R_HalfPublicProperty && 
                    T.PublicProperty == R_PublicProperty && 
                    T.PrivateField == R_PrivateField; 
                if (TestSuccess) 
                    Console.WriteLine("Success"); 
                else 
                    Console.WriteLine("Fail"); 
                #endregion 
            } 
        } 
        #endregion 
    } 
} 
 | cs | 
주의할 점
프로퍼티를 직렬화할때 Setter와 Getter가 한정자와 상관없이 모두 존재해야합니다
Setter와 Getter 중 하나가 존재하지 않으면 쓰거나 읽을때 오류가 납니다
댓글 없음:
댓글 쓰기