|
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