T4 Templates - Reading a class file given the file path - c#

I am relatively new to T4 templates. I am working in visual studio 2012 and using the tangible T4 editor. I have my text templates in one project and I want to read a class in another project and do some processing and write the generated code to a third project. I want to pass in the class file path to my template For example "C:/Code/Project2/ClassFooBar.cs" and the template will read the class from the given location and do some processing with the class properties and write the generated code to project3. I want to pass in the file path since my project has a number of class files and there is not a pattern that I can specify in the template.
My solution structure is:
SolutionFoo:
- Project1
-TextTemplate.tt
- Project2
- ClassFooBar.cs
- Project3
-GeneratedCode.cs
anyone can guide me with a clean way of passing in the class path and a way to writing the generated code to Project3?

In order to avoid the file locking issue or if you do not want to reference your Project2, try what I like to call "Design Time Reflection".
Since you have both projects (The one containing the T4 and the one containing the class you want to reflect) in the same solution, you can use the EnvDTE.CodeModel to transverse all code artifacts in your solution (Namespaces, Classes, ...) without the need to have Project2 built and referenced.
Have a look at the VisualStudio Automation. And if you are using tangible's T4 Editor, there is a free reusable template in their gallery that eases the access to the EnvDTE.CodeModel from within a T4 template.
This might be a good start point: http://t4-editor.tangible-engineering.com/blog/walking-the-visual-studio-code-model-with-t4-template.html

I recently wrote up a description of this for another question. Do not read the class file. Instead, use reflection to work with the generated class. It will be a lot simpler than trying to parse c#.
[Edit - Appending untested pseudo code]
using System.Reflection;
private void Reflect()
{
var properties = typeof(ClassFoobar).GetProperties();
var myRuntimeTemplate = new MyRuntimeTemplate();
myRuntimeTemplate.DoSomeMethodDefinedInT4(properties);
}

Related

Copy/clone an entire WPF solution& project and use it under another name

I have a WPF solution & project(written in Visual Studio2019) that I would like to use under another name.
On the other words, I have a project like( EXAMPLE_A ) that I would like to use on my other task (not creating again the entire project) just copy & paste and rename it (EXAMPLE_B) and then I want to exchange the GUI colors and title and logos...
I tried this copy&paste way but some part of code was wrong: VS said some part of code are not included in this project and so on . However, I copied the entire folder. I saw the Save As is not option... Therefore, I ask your help what is the correct process.
The question: have a simple correct way to clone/ copy the solution and use it under another separated name? ( final outcome: have EXAMPLE_A and EXAMPLE_B separately with same program functions, different name and logo)
Thank you for you all support.
Export your project as a Template in Visual Studio, then you can create another project and change the name or whatever else you need.

How to add help documentation on a method in a C# dll?

I want to add help/documentation text to a library that I am building in C#. I am using /// to create the tags and this works just fine when I use methods of my library in my lirary proyect. For example:
if my library have 2 classes Car and Person, if a I type in Person
Car.StartEngi
the auto complete of VS will suggest to use StartEngine methos and I will see the summary that for the method, fro example "This method will start the engine of the car".
But the issue comes when I compile and try to reference the dll on a separate solution. In the new solution I have already add the corresponding reference and using statement but when I write
Car.StartEngi
VS will indeed recommend to use StartEngine BUT I can not see the documentation. Does anyone know why? Do I need to add some parameter when I build the library?
P.D All the methods in the library that generates the dll are public
On the Build page of your project settings you need to turn on "XML documentation file". If you copy the XML documentation file along with your assembly then you should be able to see the documentation in other projects.

Generic Visual studio solution template

We are working asp.net projects where user customizations are released in a new project/solution called as ADDINS (for our comfort). The Structure is soemthign like this:
Solution_ClientName.sln
-> FVAddins //( Website)
->FVAddins_ClientCode_BL.csproj //(class library project)
-> SqlDbProject //(Sql Database project)
I want to know is there any way in Visual Studio , so that I can create a generic template of the same. And whenever , I have to create a new solution, I just need to fill the dynamic parts like ClientName and ClientCode and the directory structure will be ready.
Kindly note,
I do not require it using Programatically. As here's a time constraint. But programmatic approach is welcome too. I will look into that too.
Just To Help
I want it like Microsoft word template file where we have template something like <SomeField> and its get replaced by your desired text, in all over the file.
You could use a config file to this effect, all you would need to do is specify each dynamic part in the config file and load that into the solution on start-up.
Then you have a copy of the same config with different values for each copy of the template you create

Resource based on objects in WPF

In a separate project I have a de-serialized xml file with strings that I want to use in my WPF application, these strings are also used within a different project in the same solution, so I can't just move the strings over to the project holding the wpf application.
The program is structured like this:
Project A references B and C
WPF application with event handlers
Project B references C
GUI logic in F#
Project C
XML resource file and de-serializer (written in F#)
Is there a way for me to make a resource or resource dictionary based on the objects from the deserialized xml file? or can I reference the strings stored in the xml file directly?
I would suggest you to use the built-in .resx file, which is included by default in freshly created WPF application. (You can also add it at later time using Project -> Add New Item... -> Resource File.) Just be sure to set the access modifier to "Public" and you will be able to use the strings inside other projects that references the current one:
You will be able to access strings (and other resources as well!) through a strongly-typed, automatically generated wrapper class:
MessageBox.Show(WpfApplication1.Properties.Resources.String1);
You can also set properties using XAML to the strings stored in this file, using the x:Static markup extension, as desribed in (for example) this answer:
xmlns:resx="clr-namespace:WpfApplication1.Properties;assembly=WpfApplication1"
Title="{x:Static resx:Resources.String1}"
Additionally you'll get nice, Visual Studio built-in, UI for editing the file (also visible in the picture).
From what it seems your projects that will use the common resource strings will be implemented using WPF technology. In this case you could change a little the format of your xml and have directly a xaml file containing the serialized form of a ResourceDictionary. After that you can just deserialize your file and you have a ResourceDictionary. Serialization and deserialization can be done using the XamlWriter and XamlReader.
Code example:
var pc = new ParserContext
{
BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
};
...
using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
{
try
{
var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
if (resourceDictionary != null)
{
Resources.MergedDictionaries.Add(resourceDictionary);
}
}
catch
{
MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
}
}
}
The tooling in F# project is not so good, so what I have suggested in my previous answer won't work.
In C# projects, there is custom tool named "ResXFileCodeGenerator" that is run (just before the build) over the .resx file and generates the C# wrapper class. This is obviosly not available in F# projects. You have to workarounds though.
The easiest approach that comes to my mind - that is if you want to use the strongly typed wrapper generated from the C# custom tool - is to add new C# class library to your solution, which will contain the resx file and will generate the wrapper class. You can add the .resx file from Project -> Add New Item... -> Resource File. Then you can reference this library from all your F# projects and use the generated wrapper class:
open ClassLibrary1; // this is the C# library
...
let x = Resources.String1;
The second approach is to add a .resx file directly to your F# project. The funny thing here is that Visual Studio won't allow you to "Add new item" of type Resource. You can workaround this by creating Resource file in another, temporary project - for example of type C# class library, and then add the generated .resx file to your F# project using the Project -> Add Existing Item command. Then you can use the resources from the resx file using the ResourceManager class (of course without the generated properties for every resources, as in the previous case):
open Library1
open System.Resources
[<EntryPoint>]
let main argv =
// We are in the console application, which references Library1
// Library1 contains the .resx file.
let resourceManager = ResourceManager("Resources", typeof<Library1.Class1>.Assembly);
let x = resourceManager.GetString("String1");
0
Note that in the upper case I have added the resource file directly in the project (not in subfloder), as a file named Resources.resx.
You can additionally create your custom wrapper which encapsulates such calls within properties.
Turns out I managed to do something that works like I intended, but instead of using the deserialized objects, I used the xml file itself.
Here's what I did:
First I changed the XML file's Build Action from Content to Resource by going Right-click the file -> Properties -> Build Action -> Resource
Then I went into the Xaml file, and added the following to Window.Resources
<XmlDataProvider
x:Key="DropDownData"
Source="/Resource;component/Strings.xml"
XPath="/Strings/String" />
In the drop-down menu that I needed the strings I added this:
ItemsSource="{Binding Source={StaticResource DropDownData}}"
And now my strings are beautifully displayed in the WPF gui.
Thanks for your suggestions though; they may come in useful in the future.

List the names of all the classes within a VS2008 project

Is there a quick & dirty way of obtaining a list of all the classes within a Visual Studio 2008 (c#) project? There are quite a lot of them and Im just lazy enough not to want to do it manually.
If you open the "Class View" dialogue (View -> Class View or Ctrl+W, C) you can get a list of all of the classes in your project which you can then select and copy to the clipboard. The copy will send the fully qualified (i.e. with complete namespace) names of all classes that you have selected.
Maybe you can write an XSL/XSLT to display only the class names from the XML generated by the XML documentation, if you have any.
I would probably build the assembly, and then use reflection to iterate over all the exported types... If you want some sample code you can find inspiration in http://www.timvw.be/presenting-assemblytypepicker/.
I've had success using doxygen to generate documentation from the XML comments in my projects - a byproduct of this is a nice, hyperlinked list of classes.

Categories

Resources