|
6 | 6 | using System.Collections.Generic; |
7 | 7 | using System.IO; |
8 | 8 | using System.Linq; |
9 | | -using System.Reflection; |
10 | 9 | using ServiceStack.Text; |
11 | 10 | using ServiceStack.Text.Common; |
12 | 11 | using ServiceStack.Text.Json; |
13 | 12 | using System.Globalization; |
| 13 | +using System.Reflection; |
14 | 14 | using System.Reflection.Emit; |
15 | 15 |
|
16 | 16 | #if NETSTANDARD1_3 |
17 | 17 | using System.Collections.Specialized; |
18 | 18 | using System.Net; |
19 | 19 | using System.Linq.Expressions; |
20 | | -using System.Runtime.Serialization; |
21 | 20 | #endif |
22 | 21 |
|
23 | 22 | namespace ServiceStack |
@@ -439,16 +438,6 @@ private static StringCollection ParseStringCollection<TSerializer>(string value) |
439 | 438 | return result; |
440 | 439 | } |
441 | 440 | #endif |
442 | | - |
443 | | - public override Type UseType(Type type) |
444 | | - { |
445 | | - if (type.IsInterface() || type.IsAbstract()) |
446 | | - { |
447 | | - return DynamicProxy.GetInstanceFor(type).GetType(); |
448 | | - } |
449 | | - return type; |
450 | | - } |
451 | | - |
452 | 441 | public override ParseStringDelegate GetJsReaderParseMethod<TSerializer>(Type type) |
453 | 442 | { |
454 | 443 | if (type.AssignableFrom(typeof(System.Dynamic.IDynamicMetaObjectProvider)) || |
@@ -495,6 +484,87 @@ public override string GetStackTrace() |
495 | 484 | } |
496 | 485 | #endif |
497 | 486 |
|
| 487 | + public override SetPropertyDelegate GetSetPropertyMethod(PropertyInfo propertyInfo) |
| 488 | + { |
| 489 | + return CreateIlPropertySetter(propertyInfo); |
| 490 | + } |
| 491 | + |
| 492 | + public override SetPropertyDelegate GetSetFieldMethod(FieldInfo fieldInfo) |
| 493 | + { |
| 494 | + return CreateIlFieldSetter(fieldInfo); |
| 495 | + } |
| 496 | + |
| 497 | + public override SetPropertyDelegate GetSetMethod(PropertyInfo propertyInfo, FieldInfo fieldInfo) |
| 498 | + { |
| 499 | + return propertyInfo.CanWrite |
| 500 | + ? CreateIlPropertySetter(propertyInfo) |
| 501 | + : CreateIlFieldSetter(fieldInfo); |
| 502 | + } |
| 503 | + |
| 504 | + public override Type UseType(Type type) |
| 505 | + { |
| 506 | + if (type.IsInterface() || type.IsAbstract()) |
| 507 | + { |
| 508 | + return DynamicProxy.GetInstanceFor(type).GetType(); |
| 509 | + } |
| 510 | + return type; |
| 511 | + } |
| 512 | + |
| 513 | + public static SetPropertyDelegate CreateIlPropertySetter(PropertyInfo propertyInfo) |
| 514 | + { |
| 515 | + var propSetMethod = propertyInfo.SetMethod; |
| 516 | + if (propSetMethod == null) |
| 517 | + return null; |
| 518 | + |
| 519 | + var setter = CreateDynamicSetMethod(propertyInfo); |
| 520 | + |
| 521 | + var generator = setter.GetILGenerator(); |
| 522 | + generator.Emit(OpCodes.Ldarg_0); |
| 523 | + generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); |
| 524 | + generator.Emit(OpCodes.Ldarg_1); |
| 525 | + |
| 526 | + generator.Emit(propertyInfo.PropertyType.IsClass() |
| 527 | + ? OpCodes.Castclass |
| 528 | + : OpCodes.Unbox_Any, |
| 529 | + propertyInfo.PropertyType); |
| 530 | + |
| 531 | + generator.EmitCall(OpCodes.Callvirt, propSetMethod, (Type[])null); |
| 532 | + generator.Emit(OpCodes.Ret); |
| 533 | + |
| 534 | + return (SetPropertyDelegate)setter.CreateDelegate(typeof(SetPropertyDelegate)); |
| 535 | + } |
| 536 | + |
| 537 | + public static SetPropertyDelegate CreateIlFieldSetter(FieldInfo fieldInfo) |
| 538 | + { |
| 539 | + var setter = CreateDynamicSetMethod(fieldInfo); |
| 540 | + |
| 541 | + var generator = setter.GetILGenerator(); |
| 542 | + generator.Emit(OpCodes.Ldarg_0); |
| 543 | + generator.Emit(OpCodes.Castclass, fieldInfo.DeclaringType); |
| 544 | + generator.Emit(OpCodes.Ldarg_1); |
| 545 | + |
| 546 | + generator.Emit(fieldInfo.FieldType.IsClass() |
| 547 | + ? OpCodes.Castclass |
| 548 | + : OpCodes.Unbox_Any, |
| 549 | + fieldInfo.FieldType); |
| 550 | + |
| 551 | + generator.Emit(OpCodes.Stfld, fieldInfo); |
| 552 | + generator.Emit(OpCodes.Ret); |
| 553 | + |
| 554 | + return (SetPropertyDelegate)setter.CreateDelegate(typeof(SetPropertyDelegate)); |
| 555 | + } |
| 556 | + |
| 557 | + private static DynamicMethod CreateDynamicSetMethod(MemberInfo memberInfo) |
| 558 | + { |
| 559 | + var args = new[] { typeof(object), typeof(object) }; |
| 560 | + var name = string.Format("_{0}{1}_", "Set", memberInfo.Name); |
| 561 | + var returnType = typeof(void); |
| 562 | + |
| 563 | + return !memberInfo.DeclaringType.IsInterface() |
| 564 | + ? new DynamicMethod(name, returnType, args, memberInfo.DeclaringType, true) |
| 565 | + : new DynamicMethod(name, returnType, args, memberInfo.Module, true); |
| 566 | + } |
| 567 | + |
498 | 568 | public static void InitForAot() |
499 | 569 | { |
500 | 570 | } |
|
0 commit comments