Line data Source code
1 : #region Copyright
2 : // // -----------------------------------------------------------------------
3 : // // <copyright company="Chinchilla Software Limited">
4 : // // Copyright Chinchilla Software Limited. All rights reserved.
5 : // // </copyright>
6 : // // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Dynamic;
11 : using System.Linq;
12 : using System.Reflection;
13 :
14 : namespace Cqrs.Infrastructure
15 : {
16 : /// <summary>
17 : /// A universal wrapper around complex and primitive objects.
18 : /// </summary>
19 : internal class PrivateReflectionDynamicObject : DynamicObject
20 : {
21 : /// <summary>
22 : /// The original/real <see cref="object"/> this wraps.
23 : /// </summary>
24 : public object RealObject { get; set; }
25 :
26 : private const BindingFlags BindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic;
27 :
28 : internal static object WrapObjectIfNeeded(object @object)
29 : {
30 : // Don't wrap primitive types, which don't have many interesting internal APIs
31 : if (@object == null || @object.GetType().IsPrimitive || @object is string)
32 : return @object;
33 :
34 : return new PrivateReflectionDynamicObject { RealObject = @object };
35 : }
36 :
37 : /// <summary>
38 : /// Calls <see cref="InvokeMemberOnType"/> then passes the response to <see cref="WrapObjectIfNeeded"/>.
39 : /// </summary>
40 : /// <remarks>Called when a method is called.</remarks>
41 1 : public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
42 : {
43 : result = InvokeMemberOnType(RealObject.GetType(), RealObject, binder.Name, args);
44 :
45 : // Wrap the sub object if necessary. This allows nested anonymous objects to work.
46 : result = WrapObjectIfNeeded(result);
47 :
48 : return true;
49 : }
50 :
51 : private static object InvokeMemberOnType(Type type, object target, string name, object[] args)
52 : {
53 : try
54 : {
55 : if (type.GetMember(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Any())
56 : return type.InvokeMember(name, BindingFlags.InvokeMethod | BindingFlags, null, target, args);
57 : // If we couldn't find the method, try on the base class
58 : if (type.BaseType != null)
59 : return InvokeMemberOnType(type.BaseType, target, name, args);
60 : }
61 : catch (MissingMethodException)
62 : {
63 : // If we couldn't find the method, try on the base class
64 : if (type.BaseType != null)
65 : return InvokeMemberOnType(type.BaseType, target, name, args);
66 : }
67 : // Don't care if the method don't exist.
68 : return null;
69 : }
70 : }
71 : }
|