EnvDTE: How to find if a property is marked as virtual - t4

I am putting together a template for creating buddy classes for classes generated by the Entity Framework -> Reverse Engineer Code First context menu item.
I really don't want to include the navigation properties that are marked as virtual. So how, using CodeProperty interface (or other EnvDTE code) discover if a property is marked as virtual?
To say it with pseudo code:
<# foreach (CodeElement ce in classInFile.Members)
{
if (ce.Kind == vsCMElement.vsCMElementProperty && [ce not marked as virtual])
{
WriteDisplayName(ce);
WriteProperty(ce);
WriteLine("");
}
} #>
Ie, how do I determine that ce is not marked as virtual?

Cast the CodeElement to a CodeProperty2 and check its OverrideKind property.

Related

T4 iterate over projects in solution folders

I have a T4 template which generates my fluent builder classes for my api-contracts. So when i have a contract CreatePersonRequest which has a name and a firstname, i generate a CreatePersonRequestBuilder which makes the CreatePersonRequest.
This way my builders are always up to date and by inheriting one of these I can make easily various pre-filled objects with a nice syntax.
This works fine when my projects are all located in root of my solution. Once i started to add some solution folders, this didn't work anymore.
public EnvDTE.Project GetProjectByName(string projectName) {
var serviceProvider = (IServiceProvider)this.Host;
var dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
var solution = dte.Solution;
foreach (Project p in solution.Projects)
{
if (p != null) {
if (p.Name == projectName){
return p;
}
}
}
return null;
}
I retrieve all my projects from my solutions in the beginning and then iterate over these and verify the name. Apparantly the word 'project' here can also means solution folder.
Pretty easy fix I thought. Check the kind of the project (can be a project/folder/....) and in case of a folder go deeper into the ProjectItems hierarchy.
The problem I now have is that I have ProjectItem which is an interface (and not implemented by Project). So I have no way to convert this ProjectItem to a Project (altough the ProjectItem.Kind property tells me it is a Project).
How can i retrieve projects deeper into the Solution hierarchy?

Is it possible to provide UI selectable options to custom msbuild tasks?

I have built a custom msbuild task that I use to convert 3D models in the format I use in my engine. However there are some optional behaviours that I would like to provide. For example allowing the user to choose whether to compute the tangent array or not, whether to reverse the winding order of the indices, etc.
In the actual UI where you select the Build action for each file, is it possible to define custom fields that would then be fed to the input parameters of the task? Such as a "Compute Tangents" dropbox where you can choose True or False?
If that is possible, how? Are there any alternatives besides defining multiple tasks? I.e. ConvertModelTask, ConvertModelComputeTangentTask, ConvertModelReverseIndicesTask, etc.
Everything in a MsBuild Custom Task, has to have "settable properties" to drive behavior.
Option 1.
Define an ENUM-esque to drive you behavior.
From memory, the MSBuild.ExtensionPack.tasks and MSBuild.ExtensionPack.Xml.XmlFile TaskAction="ReadElementText" does this type of thing.
The "TaskAction" is the enum-esque thing. I say "esque", because all you can do on the outside is set a string. and then in the code, convert the string to an internal enum.
See code here:
http://searchcode.com/codesearch/view/14325280
Option 2: You can still use OO on the tasks. Create a BaseTask (abstract) for shared logic), and then subclass it, and make the other class a subclass, and the msbuild task that you call.
SvnExport does this. SvnClient is the base class. And it has several subclasses.
See code here:
https://github.com/loresoft/msbuildtasks/blob/master/Source/MSBuild.Community.Tasks/Subversion/SvnExport.cs
You can probably dive deep with EnvDTE or UITypeEditor but since you already have a custom task why not keep it simple with a basic WinForm?
namespace ClassLibrary1
{
public class Class1 : Task
{
public bool ComputeTangents { set { _computeTangents = value; } }
private bool? _computeTangents;
public override bool Execute()
{
if (!_computeTangents.HasValue)
using (var form1 = new Form1())
{
form1.ShowDialog();
_computeTangents = form1.checkBox1.Checked;
}
Log.LogMessage("Compute Tangents: {0}", _computeTangents.Value);
return !Log.HasLoggedErrors;
}
}
}

How to generate code in visual studio from uml modeling project depending on stereotype instead of element type?

I have class diagram with lots of classes and interfaces.
I would like to generate code for some classes by my custom templates (about 10 templates). In order to do it now I have to specify my template for each "special" class.
But I don't want to copy-paste template bindings. Instead I want to set it on root level and set for example stereotype for my special classes so that Code Generation will apply the templates only for specific classes. How can I achieve it?
I found an answer!
The only thing I need to do is to override method that checks if my template can be applied to any UML element.
I added the next code to my t4 template file to check that stereotype "auxiliary" is applied to the class:
<#+
protected override bool AppliesToElement()
{
bool isTemplate = this.Element.IsTemplate;
bool isBoundElement = this.Element.TemplateBindings != null && this.Element.TemplateBindings.Any();
return !isTemplate && !isBoundElement && GetStereotype(this.Element) == "class"
&& this.Element.AppliedStereotypes.Any(s=>s.Name == "auxiliary");
}
#>

Getting the current project directory from experimental instance of visual studio 2010?

I'm currently implementing uml validation http://msdn.microsoft.com/en-us/library/ee329482.aspx,
when i debug, it opens a new experimental instance of visual studio for me to validate uml diagrams.
Is there a way to get the path of project directory selected by the user when the experimental instance of visual studio is running??
To be more clear,
project A - has VSIX and Class library components to validate uml validation. These class Library components are added to VSIX as MEF components
when i debug Project A -> new experimental instance of VS will open-> Then creating a new project (ctrl+shift+N)-> select modelling project-> browse to the directory (to store the modelling project)->Name the Project as "MYMODEL" -> then press OK
Now, In my Project A i need the path of MYMODEL. Can you please tell me how do i get that path??
Thanks in Advance,
This is a bit roundabout, but works.
You need references to EnvDTE and Microsoft.VisualStudio.Shell.Immutable.10.0 as well as the usual bits.
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling.Validation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
namespace Validation
{
public class MyValidationExtensions
{
[Import]
public Microsoft.VisualStudio.Shell.SVsServiceProvider ServiceProvider { get; set; }
[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(
ValidationCategories.Open
| ValidationCategories.Menu)]
public void ValidateClassNames
(ValidationContext context,
// This type determines what elements
// will be validated by this method:
IModel elementToValidate)
{
IModelStore store = elementToValidate.GetModelStore();
EnvDTE.DTE dte = ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
//dynamic projects = dte.ActiveSolutionProjects;
foreach (EnvDTE.Project project in dte.Solution.Projects)
{
IModelingProject mp = project as IModelingProject;
if (mp.Store == store)
{
System.Windows.Forms.MessageBox.Show(project.FullName);
}
}
}
// Add more validation methods for different element types.
}
}

Generating code for service proxies

I'm trying to generate some additional code base on the auto-generated webservice proxies in my VS2010 solution, I'm using a T4 template to do so.
The problem is, automatically generated proxies are added in "Service Reference" folder but ProjectItems (files) are hidden by default and the following code does not find them in the project structure:
var sr = GetProjectItem(project, "Service References");
if(sr != null)
{
foreach(ProjectItem item in sr.ProjectItems)
{
foreach(var file in item.ProjectItems)
{
//Services.Add(new ServiceInfo { Name = file.Name });
}
}
}
The above code runs and although service reference is found, and there are ProjectItems under that node (named by the webservice reference name), under object under that node is of type System.__ComObject and I'm not sure how to progress.
Any help is appreciated.
It turns out I figured out how to fix this right after posting it here!
The problem was I was using the "var" keyword in second loop, and casting the "file" variable to "ProjectItem" work just like first loop.

Resources