I was using some files that have among other things some C# code in it in VS. When it dawned at me that I wasn’t getting the syntax highlighting which makes it much harder to read the code. Visual Studio just treats it as any other text file. In order to add a new one you just need to set new file association within VS. Tools - Options - Text editor - File Extensions. Add your extension and the editor you want to use, in my case Microsoft Visual C#. That will give you the code syntax, much better.
You are currently browsing articles tagged C#.
If you are like me and wonder how much coverage your unittests have you can add coverage to your Team Foundation Server builds and see for yourself.
Note, I have only tried this using VS2008
First right click /Solution items in your solution explorer Add new item, choose Test run Configuration, let’s name it CodeCoverage.testrunconfig
Choose Code coverage on the left and choose the dll’s you want covered, save and check it in.
In your build.proj file find the first PropertyGroup, at the end of it add the line about the config file. You will need this in order for MsBuild to find the configuration. Then it will look similar to the xml below. Note the path, in my case I had to add \MYPROJECT to the mix as that’s where my source gets checked out on the build machine. You can see where that is on the server or check the build log and look at what directory the file is checked out to.
…. snip
<RunConfigFile>
$(SolutionRoot)\MYPROJECT\CodeCoverage.testrunconfig
</RunConfigFile>
</PropertyGroup>
The coverage numbers will show up in the Unittest section of the build report. It is of course important to remember a well covered code does NOT mean that your unittests are any good. Most likely they are but the coverage number just means how much of the code was touched during the unittest run.
I had the need to use Base32 at work some time ago to compress numbers. I had forgotten about it until today when I ran across some old code. As I was researching implementation for a developer on another system we interact with. The problem at the time was that we had numbers that are too big to fit in the field where we needed to write it. In order to do so we needed to compress it and we choose Base32 for the task.
Simply put, you take a number and you convert it to the 32 characters in the convert table, for example.
123456789 becomes VITXVD
Of course when you have the Base32 encoded number you can decode it back to the original number. If you couldn’t do that it wouldn’t be very useful.
VITXVD becomes 123456789
| Value | Symbol | Value | Symbol | Value | Symbol | Value | Symbol | |||
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A | 9 | J | 18 | S | 27 | 3 | |||
| 1 | B | 10 | K | 19 | T | 28 | 4 | |||
| 2 | C | 11 | L | 20 | U | 29 | 5 | |||
| 3 | D | 12 | M | 21 | V | 30 | 6 | |||
| 4 | E | 13 | N | 22 | W | 31 | 7 | |||
| 5 | F | 14 | O | 23 | X | |||||
| 6 | G | 15 | P | 24 | Y | |||||
| 7 | H | 16 | Q | 25 | Z | |||||
| 8 | I | 17 | R | 26 | 2 |
Note that one and zero are not used so there is no confusion between them O and I. When shuffling data between different systems, legacy etc they might not be interpreted correctly. You can create the Base32 encoding in different ways. Therefor if your interacting with another system exchanging data that system needs to use the same encoding / decoding as your system.
Below is a C# sample Base32 code.
{
//
private const string BASE_32_ALPHABET = “ABCDEFGHIJKLMNOPQRSTUVWXYZ234567″;
private static int BASE_LENGTH = BASE_32_ALPHABET.Length;
// Encode number to base 32 string
public static string toBase32( int piNumToCode )
{
StringBuilder sRet = new StringBuilder();
// loop until nothing left
do
{
// Set the encoded character using mod
sRet.Append(BASE_32_ALPHABET[piNumToCode % BASE_LENGTH]);
// Adjust the reminder
piNumToCode = piNumToCode / BASE_LENGTH;
}
while (piNumToCode != 0);
return sRet.ToString();
}
// Decode base 32 string to a number
public static int fromBase32(string psCodedString)
{
int iRet = 0;
// Decode the alphabet
for (int i = psCodedString.Length - 1; i > -1; i–)
{ iRet = (iRet * BASE_LENGTH) + BASE_32_ALPHABET.IndexOf(psCodedString[i]); }
return iRet;
}
} // EOC
And unittests
// Make sure encoded number can be decoded correctly
public void randomBase32Test()
{
// Try some random number
string encoded = CxBase32.toBase32(123456789);
Assert.AreEqual(“VITXVD”, encoded);
int decode = CxBase32.fromBase32( encoded );
Assert.AreEqual(123456789, decode);
// Another number just for fun
encoded = CxBase32.toBase32(987654321);
Assert.AreEqual(“RF24N5″, encoded);
decode = CxBase32.fromBase32(encoded);
Assert.AreEqual(987654321, decode);
}
[Test]
// Make sure zero will return a value
public void zeroBase32Test()
{
// Zero test, should return a value as well
string encoded = CxBase32.toBase32(0);
Assert.AreEqual(“A”, encoded);
int decode = CxBase32.fromBase32(encoded);
Assert.AreEqual(0, decode);
}
Finally I had a new project were I needed some logging and on opportunity to use nLog for the first time. I have wanted to check it out in the past but it just never came to that. So here is the quick run down, the sample is from their tutorial with a slight mods from me and is really all you need to get nLog up and running quickly.
using NLog;
using NLog.Targets;
using NLog.Config;
using NLog.Win32.Targets;
// Step 1. Create configuration object
LoggingConfiguration config = new LoggingConfiguration();
// Step 2. Create targets and add them to the configuration
ColoredConsoleTarget consoleTarget = new ColoredConsoleTarget();
config.AddTarget(“console”, consoleTarget);
//
FileTarget fileTarget = new FileTarget();
config.AddTarget(“file”, fileTarget);
// Step 3. Set target properties
consoleTarget.Layout = “${date:format=HH\\:MM\\:ss}: ${message}”;
// set the file
fileTarget.FileName = CxUtil.getDataDir() + “\\log.txt”;
fileTarget.Layout = “${date:format=HH\\:MM\\:ss}: ${message}”;
// don’t clutter the hard drive
fileTarget.deleteOldFileOnStartup = true;
// Step 4. Define rules
LoggingRule rule1 = new LoggingRule(“*”, LogLevel.Debug, consoleTarget);
config.LoggingRules.Add(rule1);
// Only log to file in non debug mode
#if !DEBUG
LoggingRule rule2 = new LoggingRule(“*”, LogLevel.Debug, fileTarget);
config.LoggingRules.Add(rule2);
#endif
// Step 5. Activate the configuration
LogManager.Configuration = config;
// Create logger
Logger logger = LogManager.GetLogger(“Example”);
// Example usage
logger.Trace(“trace log message”);
logger.Debug(“debug log message”);
logger.Info(“info log message”);
logger.Warn(“warn log message”);
logger.Error(“error log message”);
logger.Fatal(“fatal log message”);
As great as Mono can be allowing you to run .net application under Win, Linux, Mac and more. There is a gotcha, if you intend to run on the Mac you can not use the Win forms. As the Win forms have limited functionality on the Mac or just don’t run, you are also required to install X11 on the Mac for starters. What you will have to do is to use the Gtk# UI libraries instead as they are by far more mature in Mono on the Mac. The strange part is that the Win forms work fine on the linux desktop under Mono.
This doesn’t make any sense, does it ? If you want cross platform UI application that you intend to run under Mono including on the Mac you need to write it that way from the start, use Mono and Gtk# to develop. That means for you MS VS .net developers you can’t use your favorite VS editor, at least not out of the box. You have to get something else like MonoDevelop. You also have to think about it if you have an old application that you want running under Mono on the Mac, you will have to go in and rip out the Win forms and replace them with the Gtk# forms.
As they put it on the Mono website,
There were two previous attempts to implement System.Windows.Forms in Mono. These initial attempts were done on top of other toolkits: first Gtk, then Wine. Each one had its share of problems, causing it to be abandoned.
I’m not bashing Mono by any means, I think it’s a great effort and well worth investing some time using Mono. Even getting involved if your so inclined. There is just that gotcha about using Win Forms that I wanted to point out to the unaware Win C# developers.
I had the need to display a sortable GridView in an Asp page. I have a collection of objects rather than a table object. What I chose to do was to convert the collection into DataView. Then it’s easy to use the built in .net sorting. The collection updates in real time, therefor a timer was added to update the grid every 15 seconds.
First the asp code
<div>
<asp:Timer ID=“Timer1″ OnTick=“Timer1_Tick” runat=“server” Interval=“15000″>
</asp:Timer>
</div>
<table>
<tr>
<td>
<asp:Label ID=“HeaderLabel” runat=“server” Text=“” />
<Triggers>
<br />
<asp:AsyncPostBackTrigger ControlID=“Timer1″ EventName=“Tick” />
</Triggers>
<asp:GridView ID=“gvCarGrid”
SkinID=“GridView”
CaptionAlign=“Top”
runat=“server”
Font-Size=“Small”
onrowdatabound=“gvCarGrid_RowDataBound”
AllowSorting=“True”
onsorting=“gvCarGrid_Sorting”
>
<Columns>
<asp:BoundField ReadOnly=“true” HeaderText=“Model” DataField=“Model”
SortExpression=“Model” />
<asp:BoundField ReadOnly=“true” HeaderText=“Year” DataField=“Year”
SortExpression=“Year” />
</asp:BoundField>
</Columns>
</asp:GridView>
</td>
</tr>
</table>
Then the C# code
//
private const string COL_MODEL = “Model”;
private const string COL_YEAR = “Year”;
//
private const string ASCENDING = ” ASC”;
private const string DESCENDING = ” DESC”;
//
private const string SORT_ORDER = “sortOrder”;
private const string SORT_COLUMN = “sortCol”;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// State variables
ViewState[SORT_ORDER] = ASCENDING;
ViewState[SORT_COLUMN] = COL_MODEL;
// Intialize
this.InitTable();
// Load the grid
this.loadGrid();
}
}
// Initialize car table to use with the view
void InitTable()
{
mCarTable = new DataTable();
mCarTable.Columns.Add(COL_MODEL);
mCarTable.Columns.Add(COL_YEAR, typeof(int));
}
// Initialize DataView from list
private DataView getDataView( IList<Car> plCars )
{
mCarTable.Rows.Clear();
foreach (Car myCar in plCars )
{
DataRow newRow = mCarTable.NewRow();
//
newRow[COL_MODEL] = myCar.Model;
newRow[COL_YEAR] = myCar.Year;
//
mCarTable.Rows.Add(newRow);
}
return new DataView(mCarTable);
}
void loadGrid()
{
IList<Car> list = getCarList();
//
this.addSortIndicator();
//
DataView carView = this.getDataView(list);
carView.Sort = ViewState[SORT_COLUMN].ToString() + ViewState[SORT_ORDER].ToString();
//
gvCarGrid.DataSource = carView;
gvCarGrid.DataBind();
}
// Call before sorting
protected void gvCarGrid_Sorting(object sender, GridViewSortEventArgs e)
{
// Set the correct direction
if( ViewState[SORT_COLUMN].ToString() == e.SortExpression &&
ViewState[SORT_ORDER].ToString() == ASCENDING )
ViewState[SORT_ORDER] = DESCENDING;
else
ViewState[SORT_ORDER] = ASCENDING;
// Set it
ViewState[SORT_COLUMN] = e.SortExpression;
// Load it
this.loadGrid();
}
private void addSortIndicator()
{
int iCount = 0;
// Search for the columm with the sort expression
foreach (DataControlField field in this.gvCarGrid.Columns )
{
// Reset the headers first
field.HeaderText = mCarTable.Columns[iCount++].ColumnName;
if (field.SortExpression == ViewState[SORT_COLUMN].ToString())
{
// Add indicator to header column
if (ViewState[SORT_ORDER].ToString() == ASCENDING)
field.HeaderText += CxUtil.ASCENDING_ARROW;
else
field.HeaderText += CxUtil.DESCENDING_ARROW;
}
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
this.loadGrid();
}
