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 #if !DOTNET35 37 namespace Google.Protobuf.Compatibility 38 { 39 /// <summary> 40 /// Provides extension methods on Type that just proxy to TypeInfo. 41 /// These are used to support the new type system from .NET 4.5, without 42 /// having calls to GetTypeInfo all over the place. While the methods here are meant to be 43 /// broadly compatible with the desktop framework, there are some subtle differences in behaviour - but 44 /// they're not expected to affect our use cases. While the class is internal, that should be fine: we can 45 /// evaluate each new use appropriately. 46 /// </summary> 47 internal static class TypeExtensions 48 { 49 /// <summary> 50 /// See https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom 51 /// </summary> IsAssignableFrom(this Type target, Type c)52 internal static bool IsAssignableFrom(this Type target, Type c) 53 { 54 return target.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo()); 55 } 56 57 /// <summary> 58 /// Returns a representation of the public property associated with the given name in the given type, 59 /// including inherited properties or null if there is no such public property. 60 /// Here, "public property" means a property where either the getter, or the setter, or both, is public. 61 /// </summary> GetProperty(this Type target, string name)62 internal static PropertyInfo GetProperty(this Type target, string name) 63 { 64 // GetDeclaredProperty only returns properties declared in the given type, so we need to recurse. 65 while (target != null) 66 { 67 var typeInfo = target.GetTypeInfo(); 68 var ret = typeInfo.GetDeclaredProperty(name); 69 if (ret != null && ((ret.CanRead && ret.GetMethod.IsPublic) || (ret.CanWrite && ret.SetMethod.IsPublic))) 70 { 71 return ret; 72 } 73 target = typeInfo.BaseType; 74 } 75 return null; 76 } 77 78 /// <summary> 79 /// Returns a representation of the public method associated with the given name in the given type, 80 /// including inherited methods. 81 /// </summary> 82 /// <remarks> 83 /// This has a few differences compared with Type.GetMethod in the desktop framework. It will throw 84 /// if there is an ambiguous match even between a private method and a public one, but it *won't* throw 85 /// if there are two overloads at different levels in the type hierarchy (e.g. class Base declares public void Foo(int) and 86 /// class Child : Base declares public void Foo(long)). 87 /// </remarks> 88 /// <exception cref="AmbiguousMatchException">One type in the hierarchy declared more than one method with the same name</exception> GetMethod(this Type target, string name)89 internal static MethodInfo GetMethod(this Type target, string name) 90 { 91 // GetDeclaredMethod only returns methods declared in the given type, so we need to recurse. 92 while (target != null) 93 { 94 var typeInfo = target.GetTypeInfo(); 95 var ret = typeInfo.GetDeclaredMethod(name); 96 if (ret != null && ret.IsPublic) 97 { 98 return ret; 99 } 100 target = typeInfo.BaseType; 101 } 102 return null; 103 } 104 } 105 } 106 #endif 107