1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2015 Google Inc. All rights reserved. 4 // https://developers.google.com/protocol-buffers/ 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 #endregion 32 33 using System; 34 using System.Reflection; 35 36 namespace Google.Protobuf.Compatibility 37 { 38 /// <summary> 39 /// Provides extension methods on Type that just proxy to TypeInfo. 40 /// These are used to support the new type system from .NET 4.5, without 41 /// having calls to GetTypeInfo all over the place. While the methods here are meant to be 42 /// broadly compatible with the desktop framework, there are some subtle differences in behaviour - but 43 /// they're not expected to affect our use cases. While the class is internal, that should be fine: we can 44 /// evaluate each new use appropriately. 45 /// </summary> 46 internal static class TypeExtensions 47 { 48 /// <summary> 49 /// Returns true if the target type is a value type, including a nullable value type or an enum, or false 50 /// if it's a reference type (class, delegate, interface - including System.ValueType and System.Enum). 51 /// </summary> IsValueType(this Type target)52 internal static bool IsValueType(this Type target) 53 { 54 return target.GetTypeInfo().IsValueType; 55 } 56 57 /// <summary> 58 /// See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom 59 /// </summary> IsAssignableFrom(this Type target, Type c)60 internal static bool IsAssignableFrom(this Type target, Type c) 61 { 62 return target.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo()); 63 } 64 65 /// <summary> 66 /// Returns a representation of the public property associated with the given name in the given type, 67 /// including inherited properties or null if there is no such public property. 68 /// Here, "public property" means a property where either the getter, or the setter, or both, is public. 69 /// </summary> GetProperty(this Type target, string name)70 internal static PropertyInfo GetProperty(this Type target, string name) 71 { 72 // GetDeclaredProperty only returns properties declared in the given type, so we need to recurse. 73 while (target != null) 74 { 75 var typeInfo = target.GetTypeInfo(); 76 var ret = typeInfo.GetDeclaredProperty(name); 77 if (ret != null && ((ret.CanRead && ret.GetMethod.IsPublic) || (ret.CanWrite && ret.SetMethod.IsPublic))) 78 { 79 return ret; 80 } 81 target = typeInfo.BaseType; 82 } 83 return null; 84 } 85 86 /// <summary> 87 /// Returns a representation of the public method associated with the given name in the given type, 88 /// including inherited methods. 89 /// </summary> 90 /// <remarks> 91 /// This has a few differences compared with Type.GetMethod in the desktop framework. It will throw 92 /// if there is an ambiguous match even between a private method and a public one, but it *won't* throw 93 /// if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and 94 /// class Child : Base declares public void Foo(long)). 95 /// </remarks> 96 /// <exception cref="AmbiguousMatchException">One type in the hierarchy declared more than one method with the same name</exception> GetMethod(this Type target, string name)97 internal static MethodInfo GetMethod(this Type target, string name) 98 { 99 // GetDeclaredMethod only returns methods declared in the given type, so we need to recurse. 100 while (target != null) 101 { 102 var typeInfo = target.GetTypeInfo(); 103 var ret = typeInfo.GetDeclaredMethod(name); 104 if (ret != null && ret.IsPublic) 105 { 106 return ret; 107 } 108 target = typeInfo.BaseType; 109 } 110 return null; 111 } 112 } 113 } 114