-
Notifications
You must be signed in to change notification settings - Fork 73
/
PropertyFetcher.cs
85 lines (75 loc) · 3.28 KB
/
PropertyFetcher.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// From https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
using System;
using System.Linq;
using System.Reflection;
namespace OpenTracing.Contrib.NetCore.Internal
{
internal class PropertyFetcher
{
private readonly string _propertyName;
private Type _expectedType;
private PropertyFetch _fetchForExpectedType;
/// <summary>
/// Make a new PropertyFetcher for a property named 'propertyName'.
/// </summary>
public PropertyFetcher(string propertyName)
{
_propertyName = propertyName;
}
/// <summary>
/// Given an object fetch the property that this PropertySpec represents.
/// </summary>
public object Fetch(object obj)
{
Type objType = obj.GetType();
if (objType != _expectedType)
{
TypeInfo typeInfo = objType.GetTypeInfo();
var propertyInfo = typeInfo.DeclaredProperties.FirstOrDefault(p => string.Equals(p.Name, _propertyName, StringComparison.InvariantCultureIgnoreCase));
_fetchForExpectedType = PropertyFetch.FetcherForProperty(propertyInfo);
_expectedType = objType;
}
return _fetchForExpectedType.Fetch(obj);
}
/// <summary>
/// PropertyFetch is a helper class. It takes a PropertyInfo and then knows how
/// to efficiently fetch that property from a .NET object (See Fetch method).
/// It hides some slightly complex generic code.
/// </summary>
private class PropertyFetch
{
/// <summary>
/// Create a property fetcher from a .NET Reflection PropertyInfo class that
/// represents a property of a particular type.
/// </summary>
public static PropertyFetch FetcherForProperty(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
return new PropertyFetch(); // returns null on any fetch.
Type typedPropertyFetcher = typeof(TypedFetchProperty<,>);
Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
propertyInfo.DeclaringType, propertyInfo.PropertyType);
return (PropertyFetch)Activator.CreateInstance(instantiatedTypedPropertyFetcher, propertyInfo);
}
/// <summary>
/// Given an object, fetch the property that this propertyFech represents.
/// </summary>
public virtual object Fetch(object obj)
{
return null;
}
private class TypedFetchProperty<TObject, TProperty> : PropertyFetch
{
public TypedFetchProperty(PropertyInfo property)
{
_propertyFetch = (Func<TObject, TProperty>)property.GetMethod.CreateDelegate(typeof(Func<TObject, TProperty>));
}
public override object Fetch(object obj)
{
return _propertyFetch((TObject)obj);
}
private readonly Func<TObject, TProperty> _propertyFetch;
}
}
}
}