T4 templates: Error on namespace - t4

I am trying to write a class in T4 template. It gives the error:
Compiling transofrmation: Type of namespace definition, or end-of-file expected
if I have the following code:
<#+
namespace Learn {
public class Converter
{
}
}
#>
But it works fine if I remove namespace
<#+
public class Converter
{
}
#>
My question is, why T4 doesn't recognize the namespace?

<#+ #> is a class feature block. Anything you put inside this block will be written inside a class statement. When you add a namespace T4 will generate and try to compile something like this:
class MyT4TempGen {
public string run() {
inside here is code that uses a string builder to build up all your <# #> tags into one big statement
}
from here down all your <#+ #> tags are added
namespace Learn {
public class Converter {
}
}
}
This is not valid C# code, namespaces can not exist within a class statement. When you do it without the namespace you will get this:
class MyT4TempGen {
public string run() {
inside here is code that uses a string builder to build up all your <# #> tags into one big statement
}
from here down all your <#+ #> tags are added
public class Converter {
}
}
Which is valid c# code, your class will be a sub class of the one the T4 compiler creates.
Here is a link to the msdn docs that explain the supported tags. See the section "Class feature control blocks". Just remember that whatever you type into a tt or t4 file will be parsed and turned into .net code so you have to follow all the normal syntax rules.

Related

T4 template to write basic class definitions

I am still trying to learn...alot. It is my understanding that neither an Interface nor Abstract class can "require" a class to have constructors. So, being pretty bad at T4's, can somebody point me in the right direction of creating a T4 template that creates the following code:
Make a T4 template that
1. reads all the classes in a file or namespace
2. produces code that has:
2.1 interface name of "I"+ClassName, e.g. "IClassName"
2.2 model name of ClassName+"Model", e.g. "ClassNameModel"
2.3 model code of:
public ClassNameModel<T>
where T: IClassName, new()
{
private readonly T t;
public ClassNameModel()
{
t = new T();
}
public ClassNameModel(T t)
{
this.t = t;
}
}
Thanks for any help. TIA

Implementing IntelliSense support for custom language (C++)

I wan to implement IntelliSense support for custom language. Actually it is a customize version of C++. i.e the methods resides in separate files
So my main class is like followings and it has import file MyClassMethods which has all the methods.
public class MyClass {
#import MyClassMethods
// my code goes here
}
So my MyClassMethods fiel looks like following and it has two methods,
public void testMethod1() {
}
public void testMethod2() {
}
Then at the end I want to have IntelliSense features when I working on MyClass. Example when I put dot character on that class in a required place I want to have testMethod1() and testMethod2() in the IntelliSense menu.
Is this possible to achieve and if so how can I achieve this?

Automation error on Webclient.Headers

I have an error in the following code when using the Headers property:
Public Function UploadImage(image As String) As String
Dim wc As System.WebClient
'create WebClient
Set wc = CreateObject("System.Net.WebClient")
Call wc.Headers.Add("Authorization", "Client-ID " & ClientId) <------- Error occurs here
I have repro'd your issue as far as possible. You didn't mention what the error you were getting was, but I got:
Automation error -2146233079 (80131509)
I tried using
CallByName(wc, "Headers", VbGet)
... but that just returns
Automation error 440.
Oh well...
I looked up online, and found this link. My guess is that because the base class of the WebHeaderCollection class is not COM Visible, this causes the error.
My work-around would be to wrap up this functionality in a small .NET component, and make that COM visible.
An example of this would be something like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace WebClientWrapper
{
[ComVisible(true)]
[Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]
public class WebClientWrapper : WebClient
{
[ComVisible(true)]
public WebHeaderCollectionWrapper WHeaders
{
get
{
return new WebHeaderCollectionWrapper(base.Headers);
}
}
}
[ComVisible(true)]
[Guid("yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy")]
public class WebHeaderCollectionWrapper
{
WebHeaderCollection _whc;
internal WebHeaderCollectionWrapper(WebHeaderCollection whc)
{
_whc = whc;
}
[ComVisible(true)]
public void Add(string name, string value)
{
_whc.Add(name, value);
}
[ComVisible(true)]
public void Clear()
{
_whc.Clear();
}
}
}
(You will have to replace the GUIDs with your own values - use GUIDGEN.EXE).
Instantiate this component with CreateObject("WebClientWrapper.WebClientWrapper")
Now you would simply replace references to the Headers property to WHeaders (or whatever you want to call it). WHeaders gives you a true wrapper around WebHeaderCollection - you'll have to define all the other wrapped methods and properties yourself. I was hoping to define WHeaders as public WebHeaderCollectionWrapper, but that didn't seem to work.
Since WebClientWrapper inherits from WebClient, you should be able to use most of the properties and methods. Where you have troubles, just add new methods to the class wrapping up the functionality that doesn't work with VB.
Oh, and do remember to set the checkbox at Project Properties => Build => Output => Register for COM interop. And then reference the type library created.

How do I declare a public enum in typescript?

For the following class:
module LayoutEngine {
enum DocumentFormat {
DOCX = 1
};
export class DocHeader {
public format : DocumentFormat;
}
}
I have two questions:
The above has a compile error where it says "Public property
'format' of exported class has or is using private type
'DocumentFormat'." but a declaration of public before the enum is
also an error. So how do I do this?
Is there a way to place the enum declaration inside the class? Just a module name isn't great for namespacing as I have a lot of classes in that module.
thanks - dave
The above has a compile error where it says "Public property 'format' of exported class has or is using private type 'DocumentFormat'.
Simply export :
module LayoutEngine {
export enum DocumentFormat {
DOCX = 1
};
export class DocHeader {
public format : DocumentFormat;
}
}
Is there a way to place the enum declaration inside the class?
the enum typescript type needs to be at a module level (a file or inside a module). Of course if you want it inside the class just use a json object
module LayoutEngine {
export class DocHeader {
DocumentFormat = {
DOCX: 1
};
public format : number;
}
}

When using Visual Studio custom templates with parameters, how can you get the actual root namespace?

I am attempting to set up a template to create a unit test class with some basic structure and default using statements. I have created a VS2010 custom template to do this and almost everything works correctly.
The issue I have encountered is that I am attempting to reference my project's base namespace in my using statements, and am unable to determine whether there is a parameter that will let me do this.
An example of what I want, assuming my project is called MyProduct.Test:
using NUnit.Framework;
using MyProduct.Test.Base;
namespace MyProduct.Test.BLL.Services.MyService
{
[TestFixture]
public class MyServiceTest : TestBase
{
[SetUp]
public void Setup()
etc...
I can generate everything except for using MyProduct.Test.Base with the template below:
using NUnit.Framework;
using $safeprojectname$.Base;
namespace $rootnamespace$
{
[TestFixture]
public class $safeitemname$ : TestBase
{
[SetUp]
public void Setup()
etc...
Unfortunately, $safeprojectname$ is only available for Project templates, not Item templates.
This template results in the following output:
using NUnit.Framework;
using $safeprojectname$.Base;
namespace MyProduct.Test.BLL.Services.MyService
{
[TestFixture]
public class MyServiceTest : TestBase
{
[SetUp]
public void Setup()
etc...
Is there any way for me to get the actual root namespace of my project (since $rootnamespace$ actually outputs the namespace for the file being added based on its location)?
Note: Obviously I can set this up to work fine for one project, but it would be much more useful to have a template that works for all projects.

Resources