1515
1616using System ;
1717using System . Collections . Generic ;
18- using System . Collections . ObjectModel ;
19- using System . Linq ;
2018using System . Linq . Expressions ;
21- using System . Reflection ;
22- using MongoDB . Bson . Serialization ;
23- using MongoDB . Driver . Linq . Linq3Implementation . Ast ;
24- using MongoDB . Driver . Linq . Linq3Implementation . Ast . Expressions ;
2519
2620namespace MongoDB . Driver . Linq . Linq3Implementation . Translators . ExpressionToAggregationExpressionTranslators
2721{
@@ -30,9 +24,6 @@ internal static class NewExpressionToAggregationExpressionTranslator
3024 public static AggregationExpression Translate ( TranslationContext context , NewExpression expression )
3125 {
3226 var expressionType = expression . Type ;
33- var constructorInfo = expression . Constructor ;
34- var arguments = expression . Arguments . ToArray ( ) ;
35- var members = expression . Members ;
3627
3728 if ( expressionType == typeof ( DateTime ) )
3829 {
@@ -50,91 +41,7 @@ public static AggregationExpression Translate(TranslationContext context, NewExp
5041 {
5142 return NewTupleExpressionToAggregationExpressionTranslator . Translate ( context , expression ) ;
5243 }
53-
54- var classMapType = typeof ( BsonClassMap < > ) . MakeGenericType ( expressionType ) ;
55- var classMap = ( BsonClassMap ) Activator . CreateInstance ( classMapType ) ;
56- var computedFields = new List < AstComputedField > ( ) ;
57-
58- // if Members is not null then trust Members more than the constructor parameter names (which are compiler generated for anonymous types)
59- if ( members == null )
60- {
61- var membersList = constructorInfo . GetParameters ( ) . Select ( p => GetMatchingMember ( expression , p . Name ) ) . ToList ( ) ;
62- members = new ReadOnlyCollection < MemberInfo > ( membersList ) ;
63- }
64-
65- for ( var i = 0 ; i < arguments . Length ; i ++ )
66- {
67- var valueExpression = arguments [ i ] ;
68- var valueTranslation = ExpressionToAggregationExpressionTranslator . Translate ( context , valueExpression ) ;
69- var valueType = valueExpression . Type ;
70- var valueSerializer = valueTranslation . Serializer ?? BsonSerializer . LookupSerializer ( valueType ) ;
71- var defaultValue = GetDefaultValue ( valueType ) ;
72- var memberMap = classMap . MapMember ( members [ i ] ) . SetSerializer ( valueSerializer ) . SetDefaultValue ( defaultValue ) ;
73- computedFields . Add ( AstExpression . ComputedField ( memberMap . ElementName , valueTranslation . Ast ) ) ;
74- }
75-
76- // map any public fields or properties that didn't match a constructor argument
77- foreach ( var member in expressionType . GetFields ( ) . Cast < MemberInfo > ( ) . Concat ( expressionType . GetProperties ( ) ) )
78- {
79- if ( ! members . Contains ( member ) )
80- {
81- var valueType = member switch
82- {
83- FieldInfo fieldInfo => fieldInfo . FieldType ,
84- PropertyInfo propertyInfo => propertyInfo . PropertyType ,
85- _ => throw new Exception ( $ "Unexpected member type: { member . MemberType } ")
86- } ;
87- var valueSerializer = context . KnownSerializersRegistry . GetSerializer ( expression , valueType ) ;
88- var defaultValue = GetDefaultValue ( valueType ) ;
89- classMap . MapMember ( member ) . SetSerializer ( valueSerializer ) . SetDefaultValue ( defaultValue ) ;
90- }
91- }
92-
93- classMap . MapConstructor ( constructorInfo , members . Select ( m => m . Name ) . ToArray ( ) ) ;
94- classMap . Freeze ( ) ;
95-
96- var ast = AstExpression . ComputedDocument ( computedFields ) ;
97- var serializerType = typeof ( BsonClassMapSerializer < > ) . MakeGenericType ( expression . Type ) ;
98- // Note that we should use context.KnownSerializersRegistry to find the serializer,
99- // but the above implementation builds up computedFields during the mapping process.
100- // We need to figure out how to resolve the serializer from KnownSerializers and then
101- // populate computedFields from that resolved serializer.
102- var serializer = ( IBsonSerializer ) Activator . CreateInstance ( serializerType , classMap ) ;
103-
104- return new AggregationExpression ( expression , ast , serializer ) ;
105- }
106-
107- private static object GetDefaultValue ( Type type )
108- {
109- if ( type . IsValueType )
110- {
111- return Activator . CreateInstance ( type ) ;
112- }
113- else
114- {
115- return null ;
116- }
117- }
118-
119- private static MemberInfo GetMatchingMember ( NewExpression expression , string constructorParameterName )
120- {
121- foreach ( var field in expression . Type . GetFields ( ) )
122- {
123- if ( field . Name . Equals ( constructorParameterName , StringComparison . OrdinalIgnoreCase ) )
124- {
125- return field ;
126- }
127- }
128-
129- foreach ( var property in expression . Type . GetProperties ( ) )
130- {
131- if ( property . Name . Equals ( constructorParameterName , StringComparison . OrdinalIgnoreCase ) )
132- {
133- return property ;
134- }
135- }
136-
137- throw new ExpressionNotSupportedException ( expression , because : $ "constructor parameter { constructorParameterName } does not match any public field or property") ;
44+ return MemberInitExpressionToAggregationExpressionTranslator . Translate ( context , expression , expression , Array . Empty < MemberBinding > ( ) ) ;
13845 }
13946 }
14047}
0 commit comments