T4 template to write basic class definitions - t4

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

Related

How to represent an function parameter as an 2D array of objects on class diagram?

Is this a right way to show the UML class diagram for the below code
public class Test {
Map<String, Map<String,Double>> bestOutput;
private Obj[] testMethod(Weight[][] input) {
}
}
I have a Test class and I also have Obj class and Weight class.
Is this class diagram correct for the above mentioned code snippets?
Thanks in advance
Is this class diagram correct for the above mentioned code snippets?
yes this is correct, and fortunately allowed by the tools
I profit of that question to also show the representation of the parameterized classes and the binding classes, if I use your example that can be :
even if in C++ we do for instance typedef Map<String, Double> String2Double; rather than class String2Double : public Map<String, Double> { ... }; (in BoUML to stereotype the class <<typedef>> produces that definition by default)

T4 templates: Error on namespace

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.

Does Subject.Subscribe only work in a static instance (or am I missing something)

I'm mucking about with reactive extensions and Iv'e hit a snag that I can't for the life of me work out what the cause is.
If I use a .NET 4 console mode app, where everything is static as follows:
using System;
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private static readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
static void Main()
{
_subject.Subscribe(RespondToNewData);
}
private static void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
DaftFrog is just a test class in my fake DAL class, this is a simple .NET 4 Class library project, the DaftFrog class, is a simple poco with a few fields in, the dal.save method just simply does a console.WriteLine of a field in the DaftFrog object.
Both classes are just simple stand in's for the real things once I get around to making the RX code work.
Anyway, back to the problem, so the code above works fine, and if I do a few
_subject.OnNext(new DaftFrog());
calls, the fake dal class, prints out what I expect and everything works fine...
HOWEVER>....
If I then transport this code as is, to a class library, and then new up that class library from within my "static program" as follows:
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
namespace RxProducer
{
public class Producer
{
private readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
private int _clock;
public void Start()
{
_subject.Subscribe(RespondToNewData);
}
public void Stop()
{
}
public void Tick()
{
if(_clock % 5 == 0)
{
DaftFrog data = new DaftFrog();
_subject.OnNext(data);
}
_clock++;
}
private void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
And then use that class in my program
using System;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Producer _myProducer = new Producer();
static void Main()
{
_myProducer.Start();
while(!line.Contains("quit"))
{
_myProducer.Tick();
line = Console.ReadLine();
}
_myProducer.Stop();
}
}
}
Then my project fails to compile.
Specifically it fails on the line:
_subject.Subscribe(RespondToNewData);
in the RxProducer class library, mores the point, the error the compiler throws back makes little sense either:
Error 1 The best overloaded method match for 'System.Reactive.Subjects.Subject<FakeDal.Entites.DaftFrog>.Subscribe(System.IObserver<FakeDal.Entites.DaftFrog>)' has some invalid arguments H:\programming\rxtesting\RxProducer\Producer.cs 17 7 RxProducer
Error 2 Argument 1: cannot convert from 'method group' to 'System.IObserver<FakeDal.Entites.DaftFrog>' H:\programming\rxtesting\RxProducer\Producer.cs 17 26 RxProducer
At first I thought that it might have been the static thing, so I made everything in the class library static, and that made no difference at all.
Iv'e really not done much with Rx until now, but I work with C# and VS 99% of the time, so I'm aware that the error is telling me it can't convert a type of some description, I just don't understand why it's telling me that, esp when the code works perfectly in the static program, but not in a class library.
Shawty
UPDATE
Second thoughts, I just know there are going to be those who insist that I post the fakedal and daft frog definitions, even though IMHO they won't be required, but to pacify the hordes of pretenders who will ask here they are :-)
using System;
namespace FakeDal
{
public class Repository<T>
{
public void Save(T entity)
{
Console.WriteLine("Here we write T to the database....");
}
}
}
namespace FakeDal.Entites
{
public class DaftFrog
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsTotalyDaft { get; set; }
}
}
Include using System; into file where you have Producer, this will help to convert RespondToNewData to IObserver<T>.
Sounds like the compiler is having trouble inferring the Action...might be missing a using statement for the relevant extension method. Alternatively, try either of:
_subject.Subscribe ((Action<DaftFrog>) RespondToData);
Or:
var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);

Freemarker - access static variables of an object

I have a simple class:
public class MyClass {
public final static long MAIN = 1;
#Setter #Getter
protected int id;
}
(#Setter #Getter are lombok annotations for Setter and Getter methods.)
In Freemarker template I would like to create a condition like:
<#if myClassInstance.id == myClassInstance.MAIN>
But the right hand side of the if expression is according to FreeMarker undefined. Is there a way to do this? Thanks!
The template language is not aware of Java classes. But you can expose static members through the data-model (template context). See: http://freemarker.org/docs/pgui_misc_beanwrapper.html#autoid_55
I know that this question already have an accepted answer but I am still writing piece of code that can be help full for some one else.
Use below piece of code in java
BeansWrapper w = new BeansWrapper();
TemplateModel statics = w.getStaticModels();
map.put("statics", statics); // map is java.util.Map
template.process(map, out); // template is freemarker.template.Template
Then access constant in ftl
${statics["com.model.to.gen.Common"].FLAG_YES}
here com.model.to.gen.Common is a class and FLAG_YES is a static constant.
You can use expose fields option. So you can use data models without accessors (getters/setters).
BeansWrapperBuilder wrapperBuilder = new BeansWrapperBuilder(Configuration.VERSION_2_3_23);
wrapperBuilder.setExposeFields(true);
Template template = freemarkerConfiguration.getTemplate("mytemplatefile.ftl");
StringWriter stringWriter = new StringWriter();
template.process(model, stringWriter, wrapperBuilder.build());
System.out.println(stringWriter.toString());
I have another similar but effective way.
First, we can create a util class like this:
/**
* FreeMarker Utils.
*
* #author Eric Chan
*/
public abstract class FreeMarkerUtils {
/**
* init for static classes and fields.
*
* #param model model
*/
public static void initStatics(final Model model) {
// you can also create the Version like: new Version("2.3.27");
BeansWrapper wrapper = new BeansWrapper(new Version(2, 3, 27));
TemplateModel statics = wrapper.getStaticModels();
model.addAttribute("statics", statics);
}
}
And next, invoke it in your Controller:
FreeMarkerUtils.initStatics(model);
That's all, now you can access static variables in your .ftl like this:
${statics["com.springboot.constants.TestConstants"].NAME}

C# Function Inheritance--Use Child Class Vars with Base Class Function

Good day, I have a fairly simple question to experienced C# programmers. Basically, I would like to have an abstract base class that contains a function that relies on the values of child classes. I have tried code similar to the following, but the compiler complains that SomeVariable is null when SomeFunction() attempts to use it.
Base class:
public abstract class BaseClass
{
protected virtual SomeType SomeVariable;
public BaseClass()
{
this.SomeFunction();
}
protected void SomeFunction()
{
//DO SOMETHING WITH SomeVariable
}
}
A child class:
public class ChildClass:BaseClass
{
protected override SomeType SomeVariable=SomeValue;
}
Now I would expect that when I do:
ChildClass CC=new ChildClass();
A new instance of ChildClass should be made and CC would run its inherited SomeFunction using SomeValue. However, this is not what happens. The compiler complains that SomeVariable is null in BaseClass. Is what I want to do even possible in C#? I have used other managed languages that allow me to do such things, so I certain I am just making a simple mistake here.
Any help is greatly appreciated, thank you.
You got it almost right, but you need to use properties instead of variables:
public abstract class BaseClass {
protected SomeType SomeProperty {get; set}
public BaseClass() {
// You cannot call this.SomeFunction() here: the property is not initialized yet
}
protected void SomeFunction() {
//DO SOMETHING WITH SomeProperty
}
}
public class ChildClass:BaseClass {
public ChildClass() {
SomeProperty=SomeValue;
}
}
You cannot use FomeFunction in the constructor because SomeProperty has not been initialized by the derived class. Outside of constructor it's fine, though. In general, accessing virtual members in the constructor should be considered suspicious.
If you must pass values from derived classes to base class constructor, it's best to do it explicitly through parameters of a protected constructor.

Resources