Showing posts with label source code. Show all posts
Showing posts with label source code. Show all posts

Monday, July 14, 2008

Simple (and funny in some way) recursy in C#

While recent work with reflections in .NET I found a funny way for recursion:

using System;

namespace ConsoleApplication1 {

class Program {

static void Main(string[] args) {
Program p =
new Program();
Console.WriteLine(p.Property);
}

public String Property {
get {
Console.WriteLine(
"Getting property, counter {0}.", counter++);
return (String)this.GetType().
GetProperty(
"Property").GetValue(this, null);
}
}
int counter = 0;
}

}
Getter of property gets PropertyInfo of itself and calls GetValue method.

Monday, December 24, 2007

New experience in C#

During last week I was doing rather interesting work: programming on C# my own Windows control similar to TextBox class. I was programming a text editor and needed to make color syntax. But RichTextBox allows to change color and other properties only for selected text, that isn't good. So I've decided to try to make my own control to work with text. Now it is rather good and implements some common functions. The most important is that I've understand that this is *really* possible, not only on paper. And through developing this control I've experience many difficulties. So now I want to write something like "How to make TextEditorControl on C#". Of course not on a professional level but I think I need to write down all this experience, while it fresh in my mind. So in future it will be easier for me to implement similar things. Moreover while writing I will unconsciously analyze what I'm writing and may be will get better solutions or completely new ideas.

Furthermore I want to write similar article about making tool to explore .NET assemblies using reflections. I already have basic implementation of such a tool and it need more polishing.

Bye.

Thursday, November 01, 2007

My Own Scripting Language for .NET Framework

I've wrote about dynamic languages and that they are good at combining already written components into full application. As I'm programming at C# now which isn't very laconic and simple language I have an idea of scripting language for .NET Framework. There are a lot of languages ported on it, among them: Python, Ruby, etc. But I still has an idea of implementing my own interpreter. It will be very useful in implementation of DSLs for my own applications. At least if I wouldn't be .NET programmer I'll get a lot of experience in developing interpreters. It's not a simple task but very interesting and useful.

Currently I'm working on library of common classes for .NET. I wasn't pleased with standard implementation because I didn't find a way for customization, e.g. changing path of saving configuration file.

Also there is a LogFile class, which implements DebugListener abstract class. I attach it to Debug to write down messages about errors.

P.S. I've passed all laboratory works in programming and think now I'll have more time for non-study programming.

Wednesday, October 24, 2007

My Example of Factory Method Pattern

I found rather useful reading a "Design Patterns" and found some examples of those patterns in programs I've written or read. And some days ago I've used one of the patterns - Factory Method.

What was the case? I've wrote two types of collections for C#: Vector (casual array) and LList (Linked List). They have the same interface ISequence and sane base abstract class SequenceBase which implements most of operations leaving virtual only basic operations, such as Insert, Remove, etc. And I wanted to have tests for all methods for both implementations. I'm using NUnit, and I didn't wanted to have two test classes with identical content, in except of operation new. So what I've made:
  1. Wrote an abstract class with all test cases (e.g. SequenceTester). All test methods have their Test tag.
  2. Class defines an abstract method Instance, which returns an object of tested interface, ISequence in my case.
  3. In all test methods I use Instance instead of operation new.
  4. For each tested class I define a test class derived from SequenceTester. In have to implement only Instance method that returns an instance of tested class and tests for an implementation of interface is ready!
The only thing I need to care is to add a test class for each implementation. Rather easy? ;) And moreover generation of concrete test classes could be delegated to special tool run before test process and building of tests.

Whats is good, as I think, is that such an approach could be used to test all implementations of each interface. Write tests for interface in abstract class, write tool to search implementations and generate required test classes and you can be sure that this interface work well in all cases, or in other case you get a pointer(s) to error(s).

I think I'll try to use this approach in my practice and write such a tool to make concrete classes for tests of interface implementations.

Off-topic: While writing this post I again faced the question: why implement array and linked list with same interface? The difference in the way they work make some operations unsuitable for one type while be good for other, so why include these operation in common interface? I think it's the question worth its own article, so I'll explore this question in future.

Sunday, October 07, 2007

Implementing custom tool in Visual Studio 2008

I've recently wrote about making tool to generate C# code. We may say that are macros for C# (it fact it is only one defined macro — for fields and properties).

And how to implement this tool? There can be two ways: write tool on scripting language that generates C# code file and is called before compilation. Another way is to use ability of Visual Studio to switch user custom tool for generating files. Firstly I've implemented tool by first way on Python and now I want to make a custom tool for Visual Studio written on C#. But how to plug custom tools in Visual Studio? Now I've got an answer, though I've spent much time to understand this.

Firstly, to develop plug-ins for Visual Studio it is needed to download Visual Studio SDK (for appropriate version of Visual Studio). I have to say that after installing it my Visual Studio 2008 Beta 2 became very unstable: IntelliSense regularly produces errors which crashes the whole Visual Studio.

After that Visual Studio will add templates of its addins. That's a base for future project (although may be addin can be created without all that stuff that is in template).

To make custom tool for generation of files the one must implement IVsSingleFileGenerator interface. I've spent a lot of time trying to make this and fails mainly because if this problem: in some places of documentation it is said that function generate gets a parameter of type out IntPtr[], in some it is said that it is out IntPtr and in fact interface has just IntPtr[]. Not any out! So how should I return value of pointer? Ok, I'm not a great specialist in .NET and arrays a sent be reference. Even if this is not a problem why there is an array not one pointer? Another outgoing parameter of function on exit must contain an amount of bytes in that array but how this will help if I'll allocate a different amount of bytes in different pointers in array. However I don't see a use for an array and just tried to allocate it and use only index 0. But this doesn't helped me and I failed in implementing that interface. May be that a bug in SDK and interface must have out IntPtr[]? Don't know I'm not a guru in Visual Studio.

I've failed to get a proper answer from MSDN documentation and my attempts so I've googled this problem.I've found some solutions but the most notable part is that in Visual Studio 2003 there was an abstract class which covered that horrible interface under much more comfortable interface. However "evil" Microsoft removed that class from version 2005. But good guys placed dll with it in Internet, i.e. here. So It's needed to implement function GetCode from that class and tool is ready to use!

However it is still needed to plug it in Visual Studio. First step is to register it as a package. This can be done by tool regpkg. It is placed in <%MVS SDK Dir%>\Tools\Bin\ directory. Just run it with a path to our compiled tool as a argument. This step can also be done manually,

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\<%MVSVersion%>\CLSID\{<%guid%>}]
@=<%Tool name%>
"InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both" "Class"=<%class name of tool%>
"Assembly"="<%asm name%>, Version=<%asm version%>, Culture=<%culture%>, PublicKeyToken=<%public key%>"


As you may noticed custom tool must be in GAC. May be there is a way to keep it somewhere else but I don't know.

What is next? Registered custom tool need to be registered as a generator. In registry dir of Visual Studio there is a directory Generators. There is some dirs in it: FA... is a C#, 16... is a VB.NET. It is needed to register tool for each language separately. In directory of proper language add directory with name of your tool, i.e. for my tool called CSGen:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{fae04ec1-301f-11d3-bf4b-00c04f79efbc}\CSGen] @="CSGen tool to generate code on C#"
"CLSID"="{<%clsid registed in \CLSID\%>}"
"GeneratesDesignTimeSource"=dword:00000001


After that start Visual Studio choose file in project and in properties type name of custom tool. After each save file will be regenerated. It is also can be forced manually: right-click on file in Solution Explorer and "Run custom tool".

These articles with examples could be helpful (I'm not a good explainer, just learning):

Wednesday, October 03, 2007

Tool to generate code on C#

While reading in "Pragmatic programmer" chapter about automation I've formed an idea of creating a tool for C# which will reduce amount of manual typed code and as a result help to avoid errors.

Now I've got only one idea for this tool, but maybe in future I've got some more. So that's an idea? In many cases I've needed to create a public property and private field to keep value of property. In some cases I also need to create an event which will happen when value of property is changed. It is a lot of similar typing work. Of course it can be made easier by Visual Studio snippets and I've used them, but this still leaves much work during maintenance:
  • while renaming I need to rename field, property and if exists event. Of course refactoring capabilities of IDE free me from necessity to search of uses of this names, but I still have to rename 2-3 elements of class.
  • I have to have separate snippets to cases when I don't want to have an event, or want to make set private. Also when this details are changed during refactoring it is needed to make them by hand.
  • It takes a lot of locs. If it be possible to write all of necessary data in one line it will be much better to read and understand.
So I've written a tool on Python which eliminates these problems. It parsers file and search for special marker in commentaries. When it founds it, tool reads options and replaces this code with a valid C# code. Lets look at example:

public event EventHandler DoubleFieldChanged;
private double _doubleField;
public double DoubleField {
get { return _doubleField; }
set {
this._doubleField = value;
if ( this.DoubleFieldChanged != null )
this.DoubleFieldChanged(this, new EventArgs());
}
}

Is an original code on C#. Most of these tokens are just speaking what is already said by others. It can be replaced by just one line:

    // @Field double Double Field

Note that name is written not as identifier but as a casual name. My tool automatically forms valid identifiers for field, property and event. And if field is renamed all identifiers are changed by program not by programmer. Moreover 10 lines are replaced by 1! Of course not in all cases such tool can give so good results.

Moreover my tool already can read some parameters of created field. Want to have set be private? No problem:

    // @Field double Double Field( private set )

And tool will make the rest. The same way I can command it not to generate event (and of course not to call it!). Of course both options can be combined together.

My tool (arrrhhh... I call it csgen!) also provides basic customization to format of output identifiers. But now csgen couldn't make complex generations. In some cases it is needed to manually create all of this code on C#.

Though I nave some ideas of making csgen more useful. For example if set needs to check incoming value. Just add to description something like: // @Field: set requires Checker.IsValid(value) and throw an ArgumentException in case of invalid value. To implement this feature I csgen will need all text after requires and paste it into if condition. Moreover in such way can be implemented some other features.

But there will be a problem: compiler will point to errors in generated code and show its line numbers. So programmer have to read faulty code in generated file and then match it with content of original file and fix errors there. Not very good.

However to finish on good news I have to say that tried to implement this feature as a 'custom tool' in Visual Studio. I'll soon write post about it, but I can say that succeeded to write module that returns IDE text and it works with it!

Monday, September 17, 2007

Asciidoc

I've recently found new tool for me: asciidoc. It is intended to create documentation in various formats from plain text. What is good that markup elements are not like but more simple symbols so text can be easily written and read without conversion to other formats. I think I'll find use for asciidoc in my projects. Documentation is always needed.

Friday, August 24, 2007

My source code library

Next programming book I want to read is "The Pragmatic Programmer" by A. Hunt and D. Thomas. While watching through it I found advice: "Never drop to garbage not-working or unused code. It will help you to avoid same mistakes" (of course that isn't very exact cite). So I've take my step to keep my knowledge base — I've started on Google Code my own project. There I'll keep my code, feeling sure that it will not disappear with hard-drive crush. And also, I'll have access to it from any place, that will have internet connection. Rather useful.

Google search through source code is also can be good to find information.