Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
485 views
in Technique[技术] by (71.8m points)

.net - Design Time Reflection

Is there a way to do reflection pre-compile - at design time?

My intent is to use T4 to spit out custom codes based on classes that implement certain interfaces. I know I can call upon reflection, but I want the T4 script to spit out the additional code before compile, otherwise I will need to compile the code twice, once to generate dlls, twice to let T4 reflect on the previously generated dll and add additional scaffolding.

Is there a way to do reflection at design time?

Is there a better way to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There actually is a way of generating code pre-build based on the CodeModel provided by Visual Studio Automation: The Project Interface provides a Property "CodeModel" that contains a graph of all model artifacts in that project. You might want to traverse it in order to find classes, interfaces, properties, ... based on which you generate your output code.

dandrejw already mentioned the Tangible T4-Editor. It has got a free template gallery. There is a reusable template "tangible Visual Studio Automation Helper" which should be extremely helpful in your case. Using this template you could solve your issue like this:

This is code within a t4 template detecting all classes that implement INotifyPropertyChanged.

<#
    // get a reference to the project of this t4 template
    var project = VisualStudioHelper.CurrentProject;
    // get all class items from the code model
    var allClasses = VisualStudioHelper.GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false);

    // iterate all classes
    foreach(EnvDTE.CodeClass codeClass in allClasses)
    {
        // get all interfaces implemented by this class
        var allInterfaces = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.ImplementedInterfaces, EnvDTE.vsCMElement.vsCMElementInterface, true);
        if (allInterfaces.OfType<EnvDTE.CodeInterface>()
                         .Any(i => i.Name == "INotifyPropertyChanged"))
        {
            #>Render your code here<#
        }
    }
#>

Put your output code where the code snippet says "Render your code here".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...