简体   繁体   中英

C# code expansion/injection in compile time

I'm looking for a way to expand/inject code at compile time, something like templates/macros/snippets...

Let's say I wrote this code in a lot of places in my application:

[JsonObject("MyProperty")]
private string MyPropertyJson { get; set; }
public object MyProperty { get; set; }

The MyPropertyJson property is used for EF mapping purposes only so I save the value is a JSON string in DB but for class users, they only know about MyProperty property.

What I want to do is, at compile time, MyPropertyJson to be expanded to this:

private string MyPropertyJson 
{
    get
    {
        return JsonConvert.SerializeObject(MyProperty);
    }
    set
    {
        MyProperty = JsonConvert.DeserializeObject(value);
    }
}

I want this to be done in the output binaries only without affecting the source code.

I know about Unity, PostSharp, Aspect-Injector, etc.. but they don't achieve what I want because by using them, I have to use some reflection to find & manipulate MyProperty but I want to expand it exactly like it's been written in the same class with access to all class internals.

It's exactly like code snippets but to be expanded during compilation phase.

A solution that doesn't cost anything extra and is supported within Visual Studio is T4 aka Text Templates . However, it does require you install the VS SDK (eg, 2015 ) and Modeling SDK (eg, 2015 ) of the version of VS that you use.

For my base class libraries , I end up dedicating an assembly for utils to use in the T4 code I write in production code. I use it in places like rolling out read/writes for primitives in IO code (eg, .TT and .CS ). Although you don't have to do this if you don't need much/complex compile time code gen.

I was able to achieve my requirement by writing a BeforeBuild msbuild target to call an external console app which I've developed to:

  1. Copy source files that will be rewritten to a temp folder
  2. Rewrite the source code in the temp files
  3. Added conditional Compile tag to the .csproj file to include manipulated source files instead of the original ones

It works like a charm :)

I'm working on a generic engine for this task and will commit it to github once finished.

The is a way to kind of get what you want.

Using implicit operators

That would need to create your own json object class for example, then add these:

class JsonObject {
    public object obj;

    public static implicit operator string(JsonObject target) { 
        return Json.SerializeObject(target.obj);
    }
}

But that won't really do what you really wanted. Almost the same as creating a new class and add functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM