|
2 | 2 | using System.Reflection;
|
3 | 3 | using NHibernate.Engine;
|
4 | 4 | using System;
|
| 5 | +using System.Collections.Concurrent; |
| 6 | +using System.Collections.Generic; |
| 7 | +using System.Runtime.CompilerServices; |
| 8 | +using Microsoft.CSharp.RuntimeBinder; |
| 9 | +using Binder = Microsoft.CSharp.RuntimeBinder.Binder; |
| 10 | + |
5 | 11 | namespace NHibernate.Properties
|
6 | 12 | {
|
7 | 13 | [Serializable]
|
8 | 14 | public class MapAccessor : IPropertyAccessor
|
9 |
| - { |
10 |
| - #region IPropertyAccessor Members |
| 15 | + { |
| 16 | + public IGetter GetGetter(System.Type theClass, string propertyName) => new MapGetter(propertyName); |
11 | 17 |
|
12 |
| - public IGetter GetGetter(System.Type theClass, string propertyName) |
13 |
| - { |
14 |
| - return new MapGetter(propertyName); |
15 |
| - } |
| 18 | + public ISetter GetSetter(System.Type theClass, string propertyName) => new MapSetter(propertyName); |
16 | 19 |
|
17 |
| - public ISetter GetSetter(System.Type theClass, string propertyName) |
18 |
| - { |
19 |
| - return new MapSetter(propertyName); |
20 |
| - } |
| 20 | + public bool CanAccessThroughReflectionOptimizer => false; |
21 | 21 |
|
22 |
| - public bool CanAccessThroughReflectionOptimizer |
23 |
| - { |
24 |
| - get { return false; } |
25 |
| - } |
26 |
| - |
27 |
| - #endregion |
28 | 22 | [Serializable]
|
29 | 23 | public sealed class MapSetter : ISetter
|
30 | 24 | {
|
31 |
| - private readonly string name; |
| 25 | + private readonly string _name; |
32 | 26 |
|
33 |
| - internal MapSetter(string name) |
34 |
| - { |
35 |
| - this.name = name; |
36 |
| - } |
| 27 | + internal MapSetter(string name) => _name = name; |
37 | 28 |
|
38 |
| - public MethodInfo Method |
39 |
| - { |
40 |
| - get { return null; } |
41 |
| - } |
| 29 | + public MethodInfo Method => null; |
42 | 30 |
|
43 |
| - public string PropertyName |
44 |
| - { |
45 |
| - get { return null; } |
46 |
| - } |
| 31 | + public string PropertyName => null; |
47 | 32 |
|
48 | 33 | public void Set(object target, object value)
|
49 | 34 | {
|
50 |
| - ((IDictionary)target)[name] = value; |
| 35 | + ((IDictionary) target)[_name] = value; |
51 | 36 | }
|
52 | 37 | }
|
| 38 | + |
53 | 39 | [Serializable]
|
54 | 40 | public sealed class MapGetter : IGetter
|
55 | 41 | {
|
56 |
| - private readonly string name; |
| 42 | + private static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> GetMemberSites = |
| 43 | + new ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>>(); |
57 | 44 |
|
58 |
| - internal MapGetter(string name) |
59 |
| - { |
60 |
| - this.name = name; |
61 |
| - } |
| 45 | + private readonly string _name; |
62 | 46 |
|
63 |
| - public MethodInfo Method |
64 |
| - { |
65 |
| - get { return null; } |
66 |
| - } |
| 47 | + internal MapGetter(string name) => _name = name; |
67 | 48 |
|
68 |
| - public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) |
69 |
| - { |
70 |
| - return Get(owner); |
71 |
| - } |
| 49 | + public MethodInfo Method => null; |
72 | 50 |
|
73 |
| - public string PropertyName |
74 |
| - { |
75 |
| - get { return null; } |
76 |
| - } |
| 51 | + public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) => Get(owner); |
77 | 52 |
|
78 |
| - public System.Type ReturnType |
79 |
| - { |
80 |
| - get { return typeof(object); } |
81 |
| - } |
| 53 | + public string PropertyName => null; |
| 54 | + |
| 55 | + public System.Type ReturnType => typeof(object); |
82 | 56 |
|
83 | 57 | public object Get(object target)
|
84 | 58 | {
|
85 |
| - return ((IDictionary)target)[name]; |
| 59 | + switch (target) |
| 60 | + { |
| 61 | + case IDictionary d: |
| 62 | + return d[_name]; |
| 63 | + case IDictionary<string, object> d: |
| 64 | + d.TryGetValue(_name, out var result); |
| 65 | + return result; |
| 66 | + default: |
| 67 | + var site = GetMemberSites.GetOrAdd( |
| 68 | + _name, |
| 69 | + name => CallSite<Func<CallSite, object, object>>.Create( |
| 70 | + Binder.GetMember( |
| 71 | + CSharpBinderFlags.None, |
| 72 | + name, |
| 73 | + target.GetType(), |
| 74 | + new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}))); |
| 75 | + |
| 76 | + return site.Target(site, target); |
| 77 | + } |
86 | 78 | }
|
87 | 79 | }
|
88 | 80 | }
|
|
0 commit comments