Metalama icon indicating copy to clipboard operation
Metalama copied to clipboard

Feature request: allow an aspect to introduce a new type

Open epsitec opened this issue 1 year ago • 11 comments

I'd like to be write an aspect to generate classes implementing data access interfaces. Currently (2023.1) my code won't work:

Example interface

interface IPerson
{
    string Name { get; }
    int Age { get; }
}

Example of the code I'd like my aspect to generate

class Person : SomeBaseClass, IPerson
{
    public Person(ISomeContext context, string name, int age) : base (context)
    {
        this.Name = name;
        this.Age = age;
    }
    public string Name { get; set; }
    public int Age { get; set; }
}

What's working, what's not working

  1. I cannot create a class from scratch (can be solved by requiring the user to write an empty class stub).
  2. I cannot create a constructor from scratch (can probably be solved by requiring the user to write an empty constructor stub).
  3. I can add the interface IPerson to Person in BuildAspect by calling builder.Advice.ImplementInterface().
  4. I can add properties Name and Age to the class by calling builder.Advice.IntroduceAutomaticProperty().
  5. I cannot make the properties show up in the interface (somehow, [InterfaceMember] should be applied dynamically).

The last point is a show-stopper for what I am intending to do. I'd love to see this feature be part of a coming release of Metalama.

epsitec avatar May 16 '23 10:05 epsitec

Hello @epsitec, thank you for submitting this issue. We will try to get back to you as soon as possible. Note to the PostSharp team, this ticket is being tracked in our dashboard under ID TP-33174.

PostSharpBot avatar May 16 '23 10:05 PostSharpBot

Here is my current attempt:


public abstract class Entity<T>
    where T : class
{ }

public interface IPerson
{
    string Name { get; }
    int Age { get; }
}

[EntityImplementation]
public class Person : Entity<IPerson>
{ }

public sealed class EntityImplementationAttribute : TypeAspect
{
    public override void BuildAspect(IAspectBuilder<INamedType> builder)
    {
        _ = builder ?? throw new ArgumentNullException (nameof (builder));

        var typeName = builder.Target.Name;
        var baseType = builder.Target.BaseType
            ?? throw new InvalidCastException ("No base type");

        if (baseType.IsGeneric == false)
        {
            throw new InvalidOperationException ($"Base type of {typeName} should be generic");
        }
        if (baseType.TypeParameters.Count != 1)
        {
            throw new InvalidOperationException ($"Base type of {typeName} should have one generic parameter");
        }

        var interfaceType = (INamedType) baseType.TypeArguments[0];

        if (interfaceType.TypeKind != TypeKind.Interface)
        {
            throw new InvalidOperationException ($"The generic type parameter <{interfaceType.ToType ().Name}> of the base type of {typeName} should be an interface, not {interfaceType.TypeKind}");
        }

        var interfaceProperties = interfaceType.AllProperties;

        foreach (var interfaceProperty in interfaceProperties)
        {
            builder.Advice.IntroduceAutomaticProperty (
                builder.Target,
                interfaceProperty.Name,
                interfaceProperty.Type.ToType (),
                OverrideStrategy.Ignore,
                b => b.Accessibility = Accessibility.Public);
        }
        /*
        builder.Advice.ImplementInterface (
            builder.Target,
            interfaceType,
            OverrideStrategy.Ignore);
        */
    }
}

epsitec avatar May 16 '23 10:05 epsitec

To upvote a feature request please add a "me too" comment because the number of emoticon reactions is not aggregated by GitHUb.

gfraiteur avatar May 17 '23 12:05 gfraiteur

me too

YBAZAN avatar May 17 '23 21:05 YBAZAN

me too

CGuidi avatar May 18 '23 06:05 CGuidi

me too

Skywalker13 avatar May 18 '23 18:05 Skywalker13

me too

WhitWaldo avatar May 18 '23 21:05 WhitWaldo

me too

rvuistin avatar May 19 '23 07:05 rvuistin

mee too

sake402 avatar Jun 16 '23 11:06 sake402

me too

CaffeinatedCoder avatar Nov 02 '23 12:11 CaffeinatedCoder

me too

niklasstich avatar Nov 22 '23 15:11 niklasstich