2007-10-05

Create object code snippet

This is another Code Snippet very usefull to me.
You can see in a previous post how to implement it in Visual Studio 2005.


<?xml version="1.0" encoding="utf-8"?>

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Title>vnew</Title>

      <Shortcut>vnew</Shortcut>

      <Description>Code snippet for create a basic new variable</Description>

      <Author>Red Line .Net</Author>

    </Header>

    <Snippet>

      <Declarations>

        <Literal Editable="true">

          <ID>type</ID>

          <ToolTip>Variable type</ToolTip>

          <Default>Object</Default>

          <Function>

          </Function>

        </Literal>

        <Literal Editable="true">

          <ID>variable</ID>

          <ToolTip>The variable backing this property</ToolTip>

          <Default>myVar</Default>

          <Function>

          </Function>

        </Literal>

        <Literal Editable="true">

          <ID>parameters</ID>

          <ToolTip>Parameters Constructor</ToolTip>

          <Default>

          </Default>

          <Function>

          </Function>

        </Literal>

      </Declarations>

      <Code Language="csharp"><![CDATA[$type$ $variable$ = new $type$($parameters$);]]></Code>

    </Snippet>

  </CodeSnippet>

  <CodeSnippet Format="1.0.0">

    <Header>

      <Title>

      </Title>

      <Shortcut>

      </Shortcut>

      <Description>

      </Description>

      <Author>

      </Author>

    </Header>

    <Snippet>

      <Code Language=""><![CDATA[]]></Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>

2007-10-02

NotImplemented Code Snippet

IntelliSense Code Snippets are reusable, task-oriented blocks of code.
This is a example to see

You must create a new file throwNotImplemented.snippet in the \Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets folder in your My Documents folder.
The snippet can be used from VS2005 IDE without another configuration.

Code to write:

<?xml version="1.0" encoding="UTF-8"?>

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Title>throw NotImplementedException</Title>

      <Author>Red Line .Net</Author>

      <Description>Create a line to throw a NotImplementionException</Description>

      <Keywords>

        <Keyword>"Exception"</Keyword>        

      </Keywords>

      <Shortcut>throwNotImplemented</Shortcut>

    </Header>

    <Snippet>

      <Declarations>

        <Literal>

          <ID>message</ID>

          <Type>String</Type>

          <ToolTip>Reason for not implementation</ToolTip>

          <Default>The method or operation is not implemented.</Default>

        </Literal>

      </Declarations>

      <Code Language="csharp" Kind="method body">

        <![CDATA[throw new NotImplementedException("$message$");

        $selected$$end$]]>

      </Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>


To use:
In a class code, write throwNotImplemented, press tab key and the IDE writes a line.

throw new Exception("The method or operation is not implemented.");

You can use the shortcuts using ctrl+K,X and you search the snippet in My Code Snippets folder

More info in http://msdn2.microsoft.com/en-us/library/ms165392(VS.80).aspx

2007-09-04

Let the computer works instead you (I)

System.CodeCom namespace can help you to avoid a lot of waste of time typing property declarations in classes when you did the work in a database or excel or xml file. And when you need to edit the class (to add a new property or field), you must edit the definition template (database, excel, xml) and go to source code to edit class file too. Microsoft give us tools to automate this class generation, lets see this tools.
Fists we see how to create a class on runtime. We use System.CodeCom namespace to create a CodeCompileUnit object. With this CodeCompileUnit you can write it to a text file to use.

Let's see a bit of code

CodeCompileUnit code = new CodeCompileUnit();

//Create a namespace
CodeNamespace unitNamespace = new CodeNamespace("MyNameSpace");
code.Namespaces.Add(unitNamespace);

//Create a class
CodeTypeDeclaration unitClass = new CodeTypeDeclaration("ClassName");
unitClass.IsPartial = true; // You can define a partial class, very useful to avoid write code in the automated file.

CodeCommentStatement coment = new CodeCommentStatement("This class 'ClassName' do nothing");
unitClass.Comments.Add(coment);


unitNamespace.Types.Add(unitClass);

//Create a field and a property related
string fieldName = "myField";
string propertyName = "MyProperty";

CodeMemberField codeField = new CodeMemberField("System.String", fieldName);
unitClass.Members.Add( codeField );

CodeMemberProperty unitProperty = new CodeMemberProperty();
unitProperty.Name = propertyName;
unitProperty.Type = new CodeTypeReference("System.String");
unitProperty.Attributes = MemberAttributes.Public;

unitProperty.GetStatements.Add( new CodeMethodReturnStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName) ) );
unitProperty.SetStatements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName), new CodePropertySetValueReferenceExpression() ) );

unitClass.Members.Add(unitProperty);


This simple code creates a CodeCompileUnit object.

Now you can traslate this object to a file.


CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider(); //Of course, you can select a Microsoft.VisualBasic.VBCodeProvider

// Create an IndentedTextWriter, constructed with a StreamWriter to the source file.
IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(filename, false), " ");
// Generate source code using the code generator.
provider.GenerateCodeFromCompileUnit(compileunit, tw, new CodeGeneratorOptions());
// Close the output file.
tw.Close();


To compile this code you need using that namespaces:
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using Microsoft.CSharp;


Of course a more complete reference is in MSDN pages (http://msdn2.microsoft.com/es-es/library/system.codedom.codecompileunit(VS.80).aspx)

2007-08-01

Open a application as simple as I can

Looking for a launcher application, i found a simple code to open a Notepad® to create a text file.
Almost we can control the Process to close after a time (3 seconds), If you need to save, you will prompt to save o cancel (but only 3 seconds again to respond, later you was forced to exit).


using System;
using System.Diagnostics;
namespace MyNamespace
{
public class MyClass
{
public static void Main()
{
Process p = Process.Start("Notepad.exe");
// Wait for 3 seconds
p.WaitForExit(3000);
if(!p.HasExited)
{
//Force to close el Notepad (if you write a text, you will prompt to save the document)
bool close = p.CloseMainWindow();
// Wait for 3 seconds again
p.WaitForExit(3000);
// The last try to close (if you don't save o discard changes when you was prompted)
if(!p.HasExited)
{
p.Kill();
}
}
p.Dispose();
}
}
}

2007-07-27

Custom Sections in app.config

Sometime you need store application configuration in a config file and .Net gives you tools to do it.
You must create a app.config file to store this data, this file must be copied to application runtime directory renamed like this: PathCopy.exe.config (I asumed that I compile my application and generates a PathCopy.exe file).

I my case I want to store a list of urls in the config file, like this:

-- app.config --
<configuration>
<configSections>
<section name="PathToCopy" type="PathCopy.PathCopyConfigurationSection, PathCopy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</configSections>
<PathToCopy>
<urls>
<add source="C:\pathSource1" target="C:\pathTarget1" lastcopy="01/12/2007 14:59:25" />
<add source="C:\pathSource2" target="C:\pathTarget2" lastcopy="01/12/2007 14:59:25" />
<add source="C:\pathSource3" target="C:\pathTarget3" lastcopy="01/12/2007 14:59:25" />
</urls>
</PathToCopy>

</configuration>
-- end app.config

Read this config file is as easy as this:

PathCopyConfigurationSection key = (PathCopyConfigurationSection)System.Configuration.ConfigurationManager.GetSection("PathToCopy");

Of course you must define the classes PathCopyConfigurationSection, PathCopyConfigurationElementCollection, PathCopyConfigurationElement first.

And you can use the read section (key) easily

foreach (PathCopyConfigurationElement key in keySection.Urls)
{
Console.WriteLine ("Coping path {0} to {1}", key.Source, key.Target);
}

As you see you can define a ConfigurationElement property from app.config element ()

[ConfigurationProperty("source")]
public string Source
{
get
{
return (string)this["source"];
}
set
{
this["source"] = value;
}
}

To configure the collection you must create the property in the ConfigurationSection class
[ConfigurationProperty("urls",
IsDefaultCollection = false)]
public PathCopyConfigurationElementCollection Urls
{
get
{
PathCopyConfigurationElementCollection urlsCollection = (PathCopyConfigurationElementCollection)base["urls"];
return urlsCollection;
}
}

And PathCopyConfigurationElementCollection only is defined to avoid casts of PathCopyConfigurationElement.

Of course, remenber add reference to System.Configuration.dll



-- code --
using System;
using System.Configuration;
namespace PathCopy {
public void Main()
{
PathCopyConfigurationSection key = (PathCopyConfigurationSection)System.Configuration.ConfigurationManager.GetSection("PathToCopy");
foreach (PathCopyConfigurationElement key in keySection.Urls)
{
Console.WriteLine ("Coping path {0} to {1}", key.Source, key.Target);
}
}

public class PathCopyConfigurationElement : ConfigurationElement
{
#region Properties
[ConfigurationProperty("source")]
public string Source
{
get
{
return (string)this["source"];
}
set
{
this["source"] = value;
}
}
[ConfigurationProperty("target")]
public string Target
{
get
{
return (string)this["target"];
}
set
{
this["target"] = value;
}
}
[ConfigurationProperty("lastcopy")]
public DateTime LastCopy
{
get
{
return (DateTime)this["lastcopy"];
}
set
{
this["lastcopy"] = value;
}
}

#endregion
#region Constructors
public PathCopyConfigurationElement()
{
}
#endregion

}

public class PathCopyConfigurationElementCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new PathCopyConfigurationElement();
}

protected override object GetElementKey(ConfigurationElement element)
{
object key = null;
PathCopyConfigurationElement myElement = element as PathCopyConfigurationElement;
if (myElement != null)
{
key = myElement.Source;
}
return key;

}
}


public class PathCopyConfigurationSection : ConfigurationSection
{

#region Properties
[ConfigurationProperty("urls",
IsDefaultCollection = false)]
public PathCopyConfigurationElementCollection Urls
{
get
{
PathCopyConfigurationElementCollection urlsCollection = (PathCopyConfigurationElementCollection)base["urls"];
return urlsCollection;
}
}

#endregion
#region Constructors
public PathCopyConfigurationSection()
{
}
#endregion
}
}
-- end code --

-- console out --
Coping path C:\pathSource1 to C:\pathTarget1
Coping path C:\pathSource2 to C:\pathTarget2
Coping path C:\pathSource3 to C:\pathTarget3
-- end console out --