Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto Detect ShouldDecompile members #165

Open
tb-mtg opened this issue Nov 18, 2020 · 0 comments
Open

Auto Detect ShouldDecompile members #165

tb-mtg opened this issue Nov 18, 2020 · 0 comments

Comments

@tb-mtg
Copy link

tb-mtg commented Nov 18, 2020

Currently I have to manually add each computed member name to a custom configuration.

It would be nice if the ShouldDecompile method below could automatically determine which properties should be decompiled:

  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)
      //***  Would be nice if auto detection was possible with non-existing methods below ***
      //|| memberInfo.AutoProperty      (One with a backing field automatically generated by the compiler)
      //|| memberInfo.HasExpressionBody (One implemented using the => (lambda) syntax)
      //|| memberInfo.HasFunctionBody   (One implemented using the normal {...} syntax)
      ;

    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);

  }

An example class:

  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);
  }

Some example extension Methods:

  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;
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant