@@ -27,6 +27,7 @@ public static class PropertiesWriter
2727 char [ ] lineSeparator = { '=' } ;
2828 int lineNum = 0 ;
2929 string readLine ;
30+ HashSet < MemberInfo > unserializedMembers = typeCachedDict . Values . ToHashSet ( ) ;
3031 while ( ( readLine = reader . ReadLine ( ) ) != null )
3132 {
3233 lineNum ++ ;
@@ -38,22 +39,23 @@ public static class PropertiesWriter
3839 if ( readLine . Contains ( '=' ) )
3940 {
4041 string [ ] keyValuePair = readLine . Split ( lineSeparator , 2 ) ;
41- keyValuePair [ 0 ] = keyValuePair [ 0 ] . ToLowerInvariant ( ) ; // Ignore case for property names in file.
42- if ( ! typeCachedDict . TryGetValue ( keyValuePair [ 0 ] , out MemberInfo member ) )
42+ // Ignore case for property names in file.
43+ if ( ! typeCachedDict . TryGetValue ( keyValuePair [ 0 ] . ToLowerInvariant ( ) , out MemberInfo member ) )
4344 {
44- Log . Warn ( $ "Property { keyValuePair [ 0 ] } does not exist on type { typeof ( T ) . FullName } !") ;
45+ Log . Warn ( $ "Property or field { keyValuePair [ 0 ] } does not exist on type { typeof ( T ) . FullName } !") ;
4546 continue ;
4647 }
48+ unserializedMembers . Remove ( member ) ; // This member was serialized in the file
4749
48- FieldInfo field = member as FieldInfo ;
49- if ( field != null )
50+ if ( ! SetMemberValue ( props , member , keyValuePair [ 1 ] ) )
5051 {
51- field . SetValue ( props , TypeDescriptor . GetConverter ( field . FieldType ) . ConvertFrom ( keyValuePair [ 1 ] ) ) ;
52- }
53- PropertyInfo prop = member as PropertyInfo ;
54- if ( prop != null )
55- {
56- prop . SetValue ( props , TypeDescriptor . GetConverter ( prop . PropertyType ) . ConvertFrom ( keyValuePair [ 1 ] ) ) ;
52+ ( Type type , object value ) data = member switch
53+ {
54+ FieldInfo field => ( field . FieldType , field . GetValue ( props ) ) ,
55+ PropertyInfo prop => ( prop . PropertyType , prop . GetValue ( props ) ) ,
56+ _ => ( typeof ( string ) , "" )
57+ } ;
58+ Log . Warn ( $@ "Property ""({ data . type . Name } ) { member . Name } "" has an invalid value { StringifyValue ( keyValuePair [ 1 ] ) } on line { lineNum } . Using default value: { StringifyValue ( data . value ) } ") ;
5759 }
5860 }
5961 else
@@ -62,6 +64,25 @@ public static class PropertiesWriter
6264 }
6365 }
6466
67+ if ( unserializedMembers . Any ( ) )
68+ {
69+ IEnumerable < string > unserializedProps = unserializedMembers . Select ( m =>
70+ {
71+ object value = null ;
72+ if ( m is FieldInfo field )
73+ {
74+ value = field . GetValue ( props ) ;
75+ }
76+ else if ( m is PropertyInfo prop )
77+ {
78+ value = prop . GetValue ( props ) ;
79+ }
80+ return new { m . Name , Value = value } ;
81+ } )
82+ . Select ( m => $ " - { m . Name } : { m . Value } ") ;
83+ Log . Warn ( $@ "{ props . FileName } is using default values for the missing properties:{ Environment . NewLine } { string . Join ( Environment . NewLine , unserializedProps ) } ") ;
84+ }
85+
6586 return props ;
6687 }
6788
@@ -121,6 +142,47 @@ private static Dictionary<string, MemberInfo> GetTypeCacheDictionary<T>()
121142 return typeCachedDict ;
122143 }
123144
145+ private static string StringifyValue ( object value )
146+ {
147+ return value switch
148+ {
149+ string _ => $@ """{ value } """,
150+ null => @"""""",
151+ _ => value.ToString()
152+ };
153+ }
154+
155+ private static bool SetMemberValue<T>(T instance, MemberInfo member, string valueFromFile)
156+ {
157+ object ConvertFromStringOrDefault ( Type typeOfValue , out bool isDefault , object defaultValue = default )
158+ {
159+ try
160+ {
161+ object newValue = TypeDescriptor . GetConverter ( typeOfValue ) . ConvertFrom ( valueFromFile ) ;
162+ isDefault = false;
163+ return newValue ;
164+ }
165+ catch ( Exception )
166+ {
167+ isDefault = true;
168+ return defaultValue ;
169+ }
170+ }
171+
172+ bool usedDefault ;
173+ switch ( member )
174+ {
175+ case FieldInfo field:
176+ field. SetValue ( instance , ConvertFromStringOrDefault ( field . FieldType , out usedDefault , field . GetValue ( instance ) ) ) ;
177+ return ! usedDefault ;
178+ case PropertyInfo prop:
179+ prop . SetValue ( instance , ConvertFromStringOrDefault ( prop . PropertyType , out usedDefault , prop . GetValue ( instance ) ) ) ;
180+ return ! usedDefault ;
181+ default :
182+ throw new Exception ( $ "Serialized member must be field or property: { member } .") ;
183+ }
184+ }
185+
124186 private static void WriteProperty < T> ( T member , object value , StreamWriter stream ) where T : MemberInfo
125187 {
126188 stream . Write ( member . Name ) ;
0 commit comments