@@ -82,44 +82,19 @@ public static ParserResult<T> Build<T>(
82
82
var specPropsWithValue =
83
83
optionSpecPropsResult . SucceededWith ( ) . Concat ( valueSpecPropsResult . SucceededWith ( ) ) . Memorize ( ) ;
84
84
85
- var setPropertyErrors = new List < Error > ( ) ;
85
+ var setPropertyErrors = new List < Error > ( ) ;
86
86
87
- Func < T > buildMutable = ( ) =>
87
+ //build the instance, determining if the type is mutable or not.
88
+ T instance ;
89
+ if ( typeInfo . IsMutable ( ) == true )
88
90
{
89
- var mutable = factory . MapValueOrDefault ( f => f ( ) , Activator . CreateInstance < T > ( ) ) ;
90
- setPropertyErrors . AddRange ( mutable . SetProperties ( specPropsWithValue , sp => sp . Value . IsJust ( ) , sp => sp . Value . FromJustOrFail ( ) ) ) ;
91
- setPropertyErrors . AddRange ( mutable . SetProperties (
92
- specPropsWithValue ,
93
- sp => sp . Value . IsNothing ( ) && sp . Specification . DefaultValue . IsJust ( ) ,
94
- sp => sp . Specification . DefaultValue . FromJustOrFail ( ) ) ) ;
95
- setPropertyErrors . AddRange ( mutable . SetProperties (
96
- specPropsWithValue ,
97
- sp =>
98
- sp . Value . IsNothing ( ) && sp . Specification . TargetType == TargetType . Sequence
99
- && sp . Specification . DefaultValue . MatchNothing ( ) ,
100
- sp => sp . Property . PropertyType . GetTypeInfo ( ) . GetGenericArguments ( ) . Single ( ) . CreateEmptyArray ( ) ) ) ;
101
- return mutable ;
102
- } ;
103
-
104
- Func < T > buildImmutable = ( ) =>
91
+ instance = BuildMutable ( factory , specPropsWithValue , setPropertyErrors ) ;
92
+ }
93
+ else
105
94
{
106
- var ctor = typeInfo . GetTypeInfo ( ) . GetConstructor ( ( from sp in specProps select sp . Property . PropertyType ) . ToArray ( ) ) ;
107
- var values = ( from prms in ctor . GetParameters ( )
108
- join sp in specPropsWithValue on prms . Name . ToLower ( ) equals sp . Property . Name . ToLower ( ) into spv
109
- from sp in spv . DefaultIfEmpty ( )
110
- select
111
- sp == null
112
- ? specProps . First ( s => String . Equals ( s . Property . Name , prms . Name , StringComparison . CurrentCultureIgnoreCase ) )
113
- . Property . PropertyType . GetDefaultValue ( )
114
- : sp . Value . GetValueOrDefault (
115
- sp . Specification . DefaultValue . GetValueOrDefault (
116
- sp . Specification . ConversionType . CreateDefaultForImmutable ( ) ) ) ) . ToArray ( ) ;
117
- var immutable = ( T ) ctor . Invoke ( values ) ;
118
- return immutable ;
119
- } ;
120
-
121
- var instance = typeInfo . IsMutable ( ) ? buildMutable ( ) : buildImmutable ( ) ;
122
-
95
+ instance = BuildImmutable ( typeInfo , factory , specProps , specPropsWithValue , setPropertyErrors ) ;
96
+ }
97
+
123
98
var validationErrors = specPropsWithValue . Validate ( SpecificationPropertyRules . Lookup ( tokens ) ) ;
124
99
125
100
var allErrors =
@@ -150,5 +125,67 @@ from sp in spv.DefaultIfEmpty()
150
125
151
126
return result ;
152
127
}
128
+
129
+ private static T BuildMutable < T > ( Maybe < Func < T > > factory , IEnumerable < SpecificationProperty > specPropsWithValue , List < Error > setPropertyErrors )
130
+ {
131
+ var mutable = factory . MapValueOrDefault ( f => f ( ) , Activator . CreateInstance < T > ( ) ) ;
132
+
133
+ setPropertyErrors . AddRange (
134
+ mutable . SetProperties (
135
+ specPropsWithValue ,
136
+ sp => sp . Value . IsJust ( ) ,
137
+ sp => sp . Value . FromJustOrFail ( )
138
+ )
139
+ ) ;
140
+
141
+ setPropertyErrors . AddRange (
142
+ mutable . SetProperties (
143
+ specPropsWithValue ,
144
+ sp => sp . Value . IsNothing ( ) && sp . Specification . DefaultValue . IsJust ( ) ,
145
+ sp => sp . Specification . DefaultValue . FromJustOrFail ( )
146
+ )
147
+ ) ;
148
+
149
+ setPropertyErrors . AddRange (
150
+ mutable . SetProperties (
151
+ specPropsWithValue ,
152
+ sp => sp . Value . IsNothing ( )
153
+ && sp . Specification . TargetType == TargetType . Sequence
154
+ && sp . Specification . DefaultValue . MatchNothing ( ) ,
155
+ sp => sp . Property . PropertyType . GetTypeInfo ( ) . GetGenericArguments ( ) . Single ( ) . CreateEmptyArray ( )
156
+ )
157
+ ) ;
158
+
159
+ return mutable ;
160
+ }
161
+
162
+ private static T BuildImmutable < T > ( Type typeInfo , Maybe < Func < T > > factory , IEnumerable < SpecificationProperty > specProps , IEnumerable < SpecificationProperty > specPropsWithValue , List < Error > setPropertyErrors )
163
+ {
164
+ var ctor = typeInfo . GetTypeInfo ( ) . GetConstructor (
165
+ specProps . Select ( sp => sp . Property . PropertyType ) . ToArray ( )
166
+ ) ;
167
+
168
+ if ( ctor == null )
169
+ {
170
+ throw new InvalidOperationException ( $ "Type appears to be immutable, but no constructor found for type { typeInfo . FullName } to accept values.") ;
171
+ }
172
+
173
+ var values =
174
+ ( from prms in ctor . GetParameters ( )
175
+ join sp in specPropsWithValue on prms . Name . ToLower ( ) equals sp . Property . Name . ToLower ( ) into spv
176
+ from sp in spv . DefaultIfEmpty ( )
177
+ select
178
+ sp == null
179
+ ? specProps . First ( s => String . Equals ( s . Property . Name , prms . Name , StringComparison . CurrentCultureIgnoreCase ) )
180
+ . Property . PropertyType . GetDefaultValue ( )
181
+ : sp . Value . GetValueOrDefault (
182
+ sp . Specification . DefaultValue . GetValueOrDefault (
183
+ sp . Specification . ConversionType . CreateDefaultForImmutable ( ) ) ) ) . ToArray ( ) ;
184
+
185
+ var immutable = ( T ) ctor . Invoke ( values ) ;
186
+
187
+ return immutable ;
188
+ }
189
+
153
190
}
154
- }
191
+ }
0 commit comments