private static bool TryLoadMembers() { // .NET Core, .NET 4.6+ s_lazyCreateFromFile = LightUpHelper.GetMethod( s_lazyMemoryMappedFileType, "CreateFromFile", FileStreamReadLightUp.FileStreamType.Value, typeof(string), typeof(long), s_lazyMemoryMappedFileAccessType, s_lazyHandleInheritabilityType, typeof(bool) ); // .NET < 4.6 if (s_lazyCreateFromFile == null) { if (s_lazyMemoryMappedFileSecurityType != null) { s_lazyCreateFromFileClassic = LightUpHelper.GetMethod( s_lazyMemoryMappedFileType, "CreateFromFile", FileStreamReadLightUp.FileStreamType.Value, typeof(string), typeof(long), s_lazyMemoryMappedFileAccessType, s_lazyMemoryMappedFileSecurityType, s_lazyHandleInheritabilityType, typeof(bool)); } if (s_lazyCreateFromFileClassic == null) { return(false); } } s_lazyCreateViewAccessor = LightUpHelper.GetMethod( s_lazyMemoryMappedFileType, "CreateViewAccessor", typeof(long), typeof(long), s_lazyMemoryMappedFileAccessType); if (s_lazyCreateViewAccessor == null) { return(false); } s_lazySafeMemoryMappedViewHandle = s_lazyMemoryMappedViewAccessorType.GetTypeInfo().GetDeclaredProperty("SafeMemoryMappedViewHandle"); if (s_lazySafeMemoryMappedViewHandle == null) { return(false); } // .NET Core, .NET 4.5.1+ s_lazyPointerOffset = s_lazyMemoryMappedViewAccessorType.GetTypeInfo().GetDeclaredProperty("PointerOffset"); // .NET < 4.5.1 if (s_lazyPointerOffset == null) { s_lazyInternalViewField = s_lazyMemoryMappedViewAccessorType.GetTypeInfo().GetDeclaredField("m_view"); if (s_lazyInternalViewField == null) { return(false); } s_lazyInternalPointerOffset = s_lazyInternalViewField.FieldType.GetTypeInfo().GetDeclaredProperty("PointerOffset"); if (s_lazyInternalPointerOffset == null) { return(false); } } return(true); }
private static Encoding_GetString LoadGetStringPlatform() { // .NET Framework 4.6+ and recent versions of other .NET platforms. // // Try to bind to Encoding.GetString(byte*, int); MethodInfo getStringInfo = LightUpHelper.GetMethod(typeof(Encoding), "GetString", typeof(byte *), typeof(int)); if (getStringInfo != null && getStringInfo.ReturnType == typeof(String)) { try { return((Encoding_GetString)getStringInfo.CreateDelegate(typeof(Encoding_GetString), null)); } catch (MemberAccessException) { } } // .NET Framework < 4.6 // // Try to bind to String.CreateStringFromEncoding(byte*, int, Encoding) // // Note that this one is internal and GetRuntimeMethod only searches public methods, which accounts for the different // pattern from above. // // NOTE: Another seeming equivalent is new string(sbyte*, int, Encoding), but don't be fooled. First of all, we can't get // a delegate to a constructor. Worst than that, even if we could, it is actually about 4x slower than both of these // and even the portable version (only ~20% slower than these) crushes it. // // It spends an inordinate amount of time transitioning to managed code from the VM and then lands in String.CreateString // (note no FromEncoding suffix), which defensively copies to a new byte array on every call -- defeating the entire purpose // of this class! // // For this reason, desktop callers should not implement an interner that falls back to the unsafe string ctor but instead // return null and let us find the best decoding approach for the current platform. // // Yet another approach is to use new string('\0', GetCharCount) and use unsafe GetChars to fill it. // However, on .NET < 4.6, there isn't no-op fast path for zero-initialization case so we'd slow down. // Plus, mutating a System.String is no better than the reflection here. IEnumerable <MethodInfo> createStringInfos = typeof(String).GetTypeInfo().GetDeclaredMethods("CreateStringFromEncoding"); foreach (var methodInfo in createStringInfos) { var parameters = methodInfo.GetParameters(); if (parameters.Length == 3 && parameters[0].ParameterType == typeof(byte *) && parameters[1].ParameterType == typeof(int) && parameters[2].ParameterType == typeof(Encoding) && methodInfo.ReturnType == typeof(String)) { try { var createStringFromEncoding = (String_CreateStringFromEncoding)methodInfo.CreateDelegate(typeof(String_CreateStringFromEncoding), null); return((encoding, bytes, byteCount) => GetStringUsingCreateStringFromEncoding(createStringFromEncoding, bytes, byteCount, encoding)); } catch (MemberAccessException) { } } } // Other platforms: Give up and fall back to GetStringPortable above. return(null); }