Closed daiplusplus closed 3 years ago
I like your first solution. I will probably implement that at first.
The second is more flexible, and I think it could be implemented additionally later.
@Jehoel I added support for to replace the type for parameters and return types. I named the attribute Substitute
. I also added support for abstract methods. They will be implemented using partial methods. Otherwise I found it problematic to come up with a sample, since everything used by the Mixin must be defined in the mixin.
Version 1.0.46 should soon be available on nuget.
I haven't added support for multiple replacements like in solution 2. I will make an new issue for that. But I'm not sure if I'll go to implement it soon.
Background problem
A major use-case for mixins is for adding operator overloads to types - however C# operator overloads are
static
and the compiler enforces special-rules that the declaring type be one or both of the parameter types. Currently the PartialMixins tooling doesn't allow us to addimplicit
operator overloads, for example.Currently, this doesn't work:
The generated mixin
class Test
is this:...which fails at compilation because the
Shared self
parameter should beTest self
, and theShared+
operator should similarly useTest
instead ofShared
for the types:Proposed solution
I'd like to be able to denote type substitutions for the mixin, which could be done with parameter attributes, like so (using a hypothetical attribute
class UseSubjectAttribute : Attribute
).Alternative solution 1
Another possibility is to allow for trivial textual transformations to be specified directly in the
Mixin
attribute, like so:When the mixin is copied into the receiver class, all parameters (and return-types) tagged with
PlaceholderAttribute(1)
are lexically replaced with"Test"
(as it's specified in[Mixin(typeof(Shared), nameof(Test) )]
) while type-names (or any text in general) inside a member function can be specified using the hypothetical attribute[TextPlaceholder]
while the method uses real types (in this casestruct PlaceholderFoo
) which gets replaced with the second value from the receiversparams String[] placeholderValues
, so the above is compiled to this:This approach has the benefit of allowing the "template" source to still compile as valid C# (so we can avoid using T4) while allowing more powerful functionality closer to C++ templates - without introducing the limitations of C#'s generics as a means of parameterisation (as mentioned below).
Alternative solution 2
I recognize that this could also be done with generics: so the mixin becomes a generic type and the mixin receiver (the subject) becomes a type-parameter, however I don't recommend this approach because that then makes it more difficult to have actual generic mixins - as well as how this mixins tooling operators at the lexical layer (like C++ templates) which affords us far more flexibility than C#'s more limited generics-constraints.