Last active
March 2, 2023 12:46
-
-
Save NickStrupat/39e659e53a7aa000b737 to your computer and use it in GitHub Desktop.
Get the backing field of an auto-property and vice versa (this only works for auto-props generated by C# compiler, and is not as good as Mono.Reflection.GetBackingField)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Text.RegularExpressions; | |
public static class AutoPropertyExtensions { | |
const String Prefix = "<"; | |
const String Suffix = ">k__BackingField"; | |
private static String GetBackingFieldName(String propertyName) => $"{Prefix}{propertyName}{Suffix}"; | |
private static String GetAutoPropertyName(String fieldName) { | |
var match = Regex.Match(fieldName, $"{Prefix}(.+?){Suffix}"); | |
return match.Success ? match.Groups[1].Value : null; | |
} | |
public static Boolean IsAnAutoProperty(this PropertyInfo propertyInfo) => propertyInfo.GetBackingField() != null; | |
public static Boolean IsBackingFieldOfAnAutoProperty(this FieldInfo propertyInfo) => propertyInfo.GetAutoProperty() != null; | |
public static FieldInfo GetBackingField(this PropertyInfo propertyInfo) { | |
if (propertyInfo == null) | |
throw new ArgumentNullException(nameof(propertyInfo)); | |
if (!propertyInfo.CanRead || !propertyInfo.GetGetMethod(nonPublic: true).IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) | |
return null; | |
var backingFieldName = GetBackingFieldName(propertyInfo.Name); | |
var backingField = propertyInfo.DeclaringType?.GetField(backingFieldName, BindingFlags.Instance | BindingFlags.NonPublic); | |
if (backingField == null) | |
return null; | |
if (!backingField.IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) | |
return null; | |
return backingField; | |
} | |
public static PropertyInfo GetAutoProperty(this FieldInfo fieldInfo) { | |
if (fieldInfo == null) | |
throw new ArgumentNullException(nameof(fieldInfo)); | |
if (!fieldInfo.IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) | |
return null; | |
var autoPropertyName = GetAutoPropertyName(fieldInfo.Name); | |
if (autoPropertyName == null) | |
return null; | |
var autoProperty = fieldInfo.DeclaringType?.GetProperty(autoPropertyName); | |
if (autoProperty == null) | |
return null; | |
if (!autoProperty.CanRead || !autoProperty.GetGetMethod(nonPublic: true).IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) | |
return null; | |
return autoProperty; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment