Generating code based on UDA

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Oct 25 08:15:21 PDT 2014


On 10/25/2014 07:45 AM, Rares Pop wrote:
> On Saturday, 25 October 2014 at 13:53:35 UTC, Adam D. Ruppe wrote:
>> On Saturday, 25 October 2014 at 13:45:29 UTC, Rares Pop wrote:
>>> What do you mean by copy/pasting ?
>>
>> I literally copied the code in your post (and fixed a missing
>> semicolon) and got it to compile.
>>
>> Passing A as an argument to injections should work. You can also use
>> this and typeof(this) inside the injections template code to access
>> the class. It should all work.
>
> Taking this one step further, it looks like the attributes are not
> available at the mixin scope.
> Here is my code:
>
> ------
>
> struct Inject {
> //    immutable Scope scoped;
> }
>
> static string injections(T)()
> {
>      pragma(msg, "injections for : ", T);
>      string result;
>      foreach(member; __traits(allMembers,T))
>      {

import std.string;

>          enum fullName = format("%s.%s", T.stringof, member);
>          pragma(msg, "member: ", fullName);
>          auto attributes = __traits(getAttributes, fullName);

You must mixin fullName:

           auto attributes = __traits(getAttributes, mixin(fullName));

>          enum dbg_msg = format ("%s attributes are %s", fullName,
> attributes.stringof);
>          pragma(msg, dbg_msg);
>          foreach(attr;attributes){

Replace the body of this foreach with the following:

             pragma(msg, "Checking attribute of type", typeof(attr));
             static if (is (typeof(attr) == Inject)) {
                 pragma(msg, "Found one");

                 // Let's inject something:
                 result ~= q{
                     int foo() {
                         return 42;
                     }
                 };
             }

>              pragma(msg, "Checking attribute", attr);
>          }
>
>      }
>      return result;
> }
>
> class A {
>
>      this(){
>      }
> }
>
> class B {
>
>      @Inject A a;

For an unknown reason to me, that UDA wants an Inject object, not the 
type itself:

     @Inject() A a;

I am puzzled with that...

>
>      mixin(injections!(B));
>
> }

Then it works with the following main:

void main()
{
     auto b = new B();
     assert(b.foo() == 42);    // It worked! :)
}

Here is the complete program:

struct Inject {
//    immutable Scope scoped;
}

static string injections(T)()
{
     pragma(msg, "injections for : ", T);
     string result;
     foreach(member; __traits(allMembers,T))
     {
         import std.string;

         enum fullName = format("%s.%s", T.stringof, member);
         pragma(msg, "member: ", fullName);
         auto attributes = __traits(getAttributes, mixin(fullName));
         enum dbg_msg = format ("%s attributes are %s", fullName, 
attributes.stringof);
         pragma(msg, dbg_msg);
         foreach(attr;attributes){
             pragma(msg, "Checking attribute of type", typeof(attr));
             static if (is (typeof(attr) == Inject)) {
                 pragma(msg, "Found one");

                 // Let's inject something:
                 result ~= q{
                     int foo() {
                         return 42;
                     }
                 };
             }
         }
     }
     return result;
}

class A {

     this(){
     }
}

class B {

     @Inject() A a;

     mixin(injections!(B));

}

void main()
{
     auto b = new B();
     assert(b.foo() == 42);    // It worked! :)
}

Ali



More information about the Digitalmars-d-learn mailing list