我使用
DelegateDecompiler,目前我需要手动将每个计算属性名称添加到自定义配置中。
如果下面的ShouldDecompile方法可以自动确定应该反编译哪些属性,那就太好了:
public class CustomDelegateDecompilerConfiguration : Configuration {
public static CustomDelegateDecompilerConfiguration Instance { get; } = new CustomDelegateDecompilerConfiguration();
public static void Enable() => Configuration.Configure(Instance);
public CustomDelegateDecompilerConfiguration() {
RegisterDecompileableMember<Person, string>(x => x.Name);
RegisterDecompileableMembers(typeof(string), nameof(string.IsNullOrWhiteSpace));
RegisterDecompileableMembers(typeof(CustomComputedMethods), new[] {
nameof(CustomComputedMethods.PersonName),
nameof(CustomComputedMethods.MonthInteger),
nameof(CustomComputedMethods.WholeMonthsBetween),
nameof(CustomComputedMethods.WholeYearsBetween)
});
}
public HashSet<MemberInfo> DecompileableMembers { get; } = new HashSet<MemberInfo>();
public override bool ShouldDecompile(MemberInfo memberInfo) => memberInfo.GetCustomAttributes(typeof(DecompileAttribute), true).Length > 0
|| memberInfo.GetCustomAttributes(typeof(ComputedAttribute), true).Length > 0
|| memberInfo.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Length > 0
|| DecompileableMembers.Contains(memberInfo)
;
public override void RegisterDecompileableMember(MemberInfo prop) => DecompileableMembers.Add(prop);
public void RegisterDecompileableMember<T, TResult>(Expression<Func<T, TResult>> expression) where T : class => RegisterDecompileableMember(expression.Body.GetMemberInfo());
public void RegisterDecompileableMembers(Type type, params string[] memberNames) {
foreach(var tmi in type.GetMembers().Where(mi => memberNames.Contains(mi.Name))) {
DecompileableMembers.Add(tmi);
}
}
public void RegisterDecompileableMembers<T>(params string[] memberNames) where T : class => RegisterDecompileableMembers(typeof(T), memberNames);
}
一个示例类:
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public string AlternativeFirstName { get; set; }
public string Name => string.Concat(AlternativeFirstName == string.Empty ? FirstName : AlternativeFirstName, " ", LastName);
}
一些示例扩展方法:
public static class CustomComputedMethods {
public static string PersonName(string firstName, string lastName, string knownAs) => (knownAs ?? firstName).Trim() + " " + lastName.Trim();
public static long MonthInteger(this DateTime d) => checked(d.Year * 12 + d.Month);
public static int WholeMonthsBetween(this DateTime d, DateTime maxDate) => (int)(maxDate.MonthInteger() - d.MonthInteger() - (d.Day > maxDate.Day ? 1 : 0));
public static int WholeYearsBetween(this DateTime d, DateTime maxDate) => d.WholeMonthsBetween(maxDate) / 12;
}
public int FooLength => foo.Length;
呢?如果属性只是读取另一个属性而不是一个字段呢?这里有各种微妙之处... - Jon Skeet