|
6 | 6 | using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
|
7 | 7 | using Microsoft.EntityFrameworkCore.Design.Internal;
|
8 | 8 | using Microsoft.EntityFrameworkCore.Internal;
|
| 9 | +using Microsoft.EntityFrameworkCore.Metadata; |
9 | 10 | using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
10 | 11 | using Microsoft.EntityFrameworkCore.Query.Internal;
|
11 | 12 |
|
@@ -1179,18 +1180,7 @@ private void Create(
|
1179 | 1180 | var valueComparerType = (Type?)property[CoreAnnotationNames.ValueComparerType];
|
1180 | 1181 | if (valueComparerType != null)
|
1181 | 1182 | {
|
1182 |
| - AddNamespace(valueComparerType, parameters.Namespaces); |
1183 |
| - |
1184 |
| - var valueComparerString = $"new {_code.Reference(valueComparerType)}()"; |
1185 |
| - if (property.ClrType.IsNullableValueType()) |
1186 |
| - { |
1187 |
| - var valueComparerElementType = ((ValueComparer)Activator.CreateInstance(valueComparerType)!).Type; |
1188 |
| - if (!valueComparerElementType.IsNullableValueType()) |
1189 |
| - { |
1190 |
| - AddNamespace(typeof(NullableValueComparer<>), parameters.Namespaces); |
1191 |
| - valueComparerString = $"new NullableValueComparer<{_code.Reference(valueComparerType)}>({valueComparerString})"; |
1192 |
| - } |
1193 |
| - } |
| 1183 | + var valueComparerString = CreateValueComparerType(valueComparerType, property.ClrType, parameters); |
1194 | 1184 |
|
1195 | 1185 | mainBuilder.AppendLine(",")
|
1196 | 1186 | .Append("valueComparer: ")
|
@@ -1240,11 +1230,13 @@ private void Create(
|
1240 | 1230 | && converter != null
|
1241 | 1231 | && property[CoreAnnotationNames.ValueConverter] != null
|
1242 | 1232 | && !parameters.ForNativeAot;
|
| 1233 | + var typeMappingSet = false; |
1243 | 1234 |
|
1244 | 1235 | if (parameters.ForNativeAot
|
1245 | 1236 | || (shouldSetConverter && converter!.MappingHints != null))
|
1246 | 1237 | {
|
1247 | 1238 | shouldSetConverter = false;
|
| 1239 | + typeMappingSet = true; |
1248 | 1240 | mainBuilder.Append(variableName).Append(".TypeMapping = ");
|
1249 | 1241 | _annotationCodeGenerator.Create(property.GetTypeMapping(), property, propertyParameters);
|
1250 | 1242 | mainBuilder.AppendLine(";");
|
@@ -1311,14 +1303,151 @@ private void Create(
|
1311 | 1303 | .AppendLine(");");
|
1312 | 1304 | }
|
1313 | 1305 |
|
| 1306 | + var elementType = property.GetElementType(); |
| 1307 | + if (elementType != null) |
| 1308 | + { |
| 1309 | + Check.DebugAssert(property.IsPrimitiveCollection, $"{property.Name} has an element type, but it's not a primitive collection."); |
| 1310 | + Create(elementType, typeMappingSet, propertyParameters); |
| 1311 | + } |
| 1312 | + |
1314 | 1313 | CreateAnnotations(
|
1315 | 1314 | property,
|
1316 | 1315 | _annotationCodeGenerator.Generate,
|
1317 |
| - parameters with { TargetName = variableName }); |
| 1316 | + propertyParameters); |
1318 | 1317 |
|
1319 | 1318 | mainBuilder.AppendLine();
|
1320 | 1319 | }
|
1321 | 1320 |
|
| 1321 | + private void Create(IElementType elementType, bool typeMappingSet, CSharpRuntimeAnnotationCodeGeneratorParameters parameters) |
| 1322 | + { |
| 1323 | + var mainBuilder = parameters.MainBuilder; |
| 1324 | + var elementVariableName = _code.Identifier(parameters.TargetName + "ElementType", elementType, parameters.ScopeObjects, capitalize: false); |
| 1325 | + var elementParameters = parameters with { TargetName = elementVariableName }; |
| 1326 | + |
| 1327 | + mainBuilder |
| 1328 | + .Append("var ").Append(elementVariableName).Append(" = ") |
| 1329 | + .Append(parameters.TargetName).Append(".SetElementType(").IncrementIndent() |
| 1330 | + .Append(_code.Literal(elementType.ClrType)); |
| 1331 | + |
| 1332 | + if (elementType.IsNullable) |
| 1333 | + { |
| 1334 | + mainBuilder.AppendLine(",") |
| 1335 | + .Append("nullable: ") |
| 1336 | + .Append(_code.Literal(elementType.IsNullable)); |
| 1337 | + } |
| 1338 | + |
| 1339 | + if (elementType.GetMaxLength() != null) |
| 1340 | + { |
| 1341 | + mainBuilder.AppendLine(",") |
| 1342 | + .Append("maxLength: ") |
| 1343 | + .Append(_code.Literal(elementType.GetMaxLength())); |
| 1344 | + } |
| 1345 | + |
| 1346 | + if (elementType.IsUnicode() != null) |
| 1347 | + { |
| 1348 | + mainBuilder.AppendLine(",") |
| 1349 | + .Append("unicode: ") |
| 1350 | + .Append(_code.Literal(elementType.IsUnicode())); |
| 1351 | + } |
| 1352 | + |
| 1353 | + if (elementType.GetPrecision() != null) |
| 1354 | + { |
| 1355 | + mainBuilder.AppendLine(",") |
| 1356 | + .Append("precision: ") |
| 1357 | + .Append(_code.Literal(elementType.GetPrecision())); |
| 1358 | + } |
| 1359 | + |
| 1360 | + if (elementType.GetScale() != null) |
| 1361 | + { |
| 1362 | + mainBuilder.AppendLine(",") |
| 1363 | + .Append("scale: ") |
| 1364 | + .Append(_code.Literal(elementType.GetScale())); |
| 1365 | + } |
| 1366 | + |
| 1367 | + var providerClrType = elementType.GetProviderClrType(); |
| 1368 | + if (providerClrType != null) |
| 1369 | + { |
| 1370 | + AddNamespace(providerClrType, parameters.Namespaces); |
| 1371 | + mainBuilder.AppendLine(",") |
| 1372 | + .Append("providerClrType: ") |
| 1373 | + .Append(_code.Literal(providerClrType)); |
| 1374 | + } |
| 1375 | + |
| 1376 | + var jsonValueReaderWriterType = (Type?)elementType[CoreAnnotationNames.JsonValueReaderWriterType]; |
| 1377 | + if (jsonValueReaderWriterType != null) |
| 1378 | + { |
| 1379 | + mainBuilder.AppendLine(",") |
| 1380 | + .Append("jsonValueReaderWriter: "); |
| 1381 | + CSharpRuntimeAnnotationCodeGenerator.CreateJsonValueReaderWriter(jsonValueReaderWriterType, parameters, _code); |
| 1382 | + } |
| 1383 | + |
| 1384 | + mainBuilder |
| 1385 | + .AppendLine(");") |
| 1386 | + .DecrementIndent(); |
| 1387 | + |
| 1388 | + var converter = elementType.FindTypeMapping()?.Converter; |
| 1389 | + var shouldSetConverter = providerClrType == null |
| 1390 | + && converter != null |
| 1391 | + && elementType[CoreAnnotationNames.ValueConverter] != null |
| 1392 | + && !parameters.ForNativeAot; |
| 1393 | + |
| 1394 | + if (parameters.ForNativeAot |
| 1395 | + || (shouldSetConverter && converter!.MappingHints != null)) |
| 1396 | + { |
| 1397 | + shouldSetConverter = false; |
| 1398 | + mainBuilder.Append(elementVariableName).Append(".TypeMapping = "); |
| 1399 | + |
| 1400 | + if (typeMappingSet) |
| 1401 | + { |
| 1402 | + mainBuilder.Append(parameters.TargetName).Append(".TypeMapping.ElementTypeMapping"); |
| 1403 | + } |
| 1404 | + else |
| 1405 | + { |
| 1406 | + _annotationCodeGenerator.Create(elementType.GetTypeMapping(), elementParameters); |
| 1407 | + } |
| 1408 | + |
| 1409 | + mainBuilder.AppendLine(";"); |
| 1410 | + } |
| 1411 | + |
| 1412 | + if (shouldSetConverter) |
| 1413 | + { |
| 1414 | + mainBuilder.Append(elementVariableName).Append(".SetValueConverter("); |
| 1415 | + _annotationCodeGenerator.Create(converter!, parameters); |
| 1416 | + mainBuilder.AppendLine(");"); |
| 1417 | + } |
| 1418 | + |
| 1419 | + var valueComparer = elementType.GetValueComparer(); |
| 1420 | + var typeMappingComparer = elementType.GetTypeMapping().Comparer; |
| 1421 | + if ((!parameters.ForNativeAot || valueComparer != typeMappingComparer) |
| 1422 | + && (parameters.ForNativeAot || elementType[CoreAnnotationNames.ValueComparer] != null)) |
| 1423 | + { |
| 1424 | + SetValueComparer(valueComparer, typeMappingComparer, nameof(CoreTypeMapping.Comparer), elementParameters); |
| 1425 | + } |
| 1426 | + |
| 1427 | + CreateAnnotations( |
| 1428 | + elementType, |
| 1429 | + _annotationCodeGenerator.Generate, |
| 1430 | + elementParameters); |
| 1431 | + } |
| 1432 | + |
| 1433 | + private string CreateValueComparerType(Type valueComparerType, Type clrType, CSharpRuntimeAnnotationCodeGeneratorParameters parameters) |
| 1434 | + { |
| 1435 | + AddNamespace(valueComparerType, parameters.Namespaces); |
| 1436 | + |
| 1437 | + var valueComparerString = $"new {_code.Reference(valueComparerType)}()"; |
| 1438 | + if (clrType.IsNullableValueType()) |
| 1439 | + { |
| 1440 | + var valueComparerElementType = ((ValueComparer)Activator.CreateInstance(valueComparerType)!).Type; |
| 1441 | + if (!valueComparerElementType.IsNullableValueType()) |
| 1442 | + { |
| 1443 | + AddNamespace(typeof(NullableValueComparer<>), parameters.Namespaces); |
| 1444 | + valueComparerString = $"new NullableValueComparer<{_code.Reference(valueComparerType)}>({valueComparerString})"; |
| 1445 | + } |
| 1446 | + } |
| 1447 | + |
| 1448 | + return valueComparerString; |
| 1449 | + } |
| 1450 | + |
1322 | 1451 | private void SetValueComparer(
|
1323 | 1452 | ValueComparer valueComparer,
|
1324 | 1453 | ValueComparer typeMappingComparer,
|
|
0 commit comments