Showing posts with label Code Samples. Show all posts
Showing posts with label Code Samples. Show all posts

Wednesday, October 10, 2007

Do you use goto in C#?

Looking through the code for the SmtpClient.Send method in Reflector and found this snippet:

switch (this.DeliveryMethod)
{
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
if (this.EnableSsl)
{
throw new SmtpException(SR.GetString(
"SmtpPickupDirectoryDoesnotSupportSsl"));
}
break
;
case SmtpDeliveryMethod.PickupDirectoryFromIis:
if (this.EnableSsl)
{
throw new SmtpException(SR.GetString(
"SmtpPickupDirectoryDoesnotSupportSsl"
));
}
goto
Label_021C;
default:
goto Label_022B;
}
MailWriter fileMailWriter =
this.GetFileMailWriter(
this.PickupDirectoryLocation);
goto
Label_025D;
Label_021C:
fileMailWriter = this.GetFileMailWriter(
IisPickupDirectory.GetPickupDirectory());

goto
Label_025D;
Label_022B:
this.GetConnection();
fileMailWriter =
this.transport.SendMail((message.Sender != null) ?
message.Sender : message.From, recipients,
message.BuildDeliveryStatusNotificationString(),
out exception);
Label_025D:
this.message = message;
message.Send(fileMailWriter,
this.DeliveryMethod != SmtpDeliveryMethod.Network);
fileMailWriter.Close();

this
.transport.ReleaseConnection();
if
((this.DeliveryMethod == SmtpDeliveryMethod.Network) && (exception != null))
{
throw exception;
}

I've always been taught to avoid goto like the plague, and it's something I've followed for years. I've never even considered it to be an option when writing code.

Thinking about it though, I did read an article a few years ago (which I can't find now) which said you could credibly use gotos only if you used it to jump down code, and not up: a rule that is stuck to here.

The thing is, I know this code can be written without using goto. But also, it might not be as readable as it is now.

I'm conflicted. But I'm sticking to the "no goto" rule until someone can come up with an example that really can't be coded without using a goto.

Tuesday, September 04, 2007

Essential SQL Server Date, Time and DateTime Functions

Just found this article on Essential SQL Server Date, Time and DateTime Functions. Has some handy functions you can add to get the following:

  • Get just the date part of a DateTime value
  • Get the time part of a DateTime value
  • Create a DateTime value with explicit Day, Month, Year, Hour Minute and Second parts
  • Create just a time value (with the date section set to a 'base' date)

Wednesday, May 23, 2007

Documenting Enum Values

If you maintain a codebase that is of any decent size, chances are you'll have defined a fair few enum types. You may also need these types and their values to be documented somewhere, as not everyone who needs them could have access to the code where they are defined.

You could of course do this manually, but if you already have lots of types this could be tedious. Luckily its quite simple to write something that will do this for you.

The code below takes a parameter for the assembly path and name, and writes the values to the Console.



private static void DumpAssemblyEnums(string assemblyPath)
{
StringBuilder builder = new StringBuilder();

// flag to check if we should put the string we
// create into the Console output
bool hasEntriesToShow = false;
try
{
builder.AppendLine(string.Format("===== {0} =====", assemblyPath));

// load assembly from the path
Assembly assembly = Assembly.LoadFrom(assemblyPath);

// get the types from this assembly
Type[] assemblyTypes = assembly.GetTypes();

for (int i = 0; i < assemblyTypes.Length; i++)
{
try
{
// check if the type is an enum
if (assemblyTypes[i].IsEnum)
{
hasEntriesToShow = true;

// output the full type name of this enum
builder.AppendLine(
string.Format("==== {0} ====",
assemblyTypes[i].FullName));

// get the values for the enum type
Array array = Enum.GetValues(assemblyTypes[i]);

// loop through the array
for (int j = 0; j < array.Length; j++)
{
// output the numeric value by converting to a
// long
// use long as enum values can be larger than
// an int
builder.AppendLine(
" " + Convert.ToInt64(array.GetValue(j)) +
" = " + array.GetValue(j).ToString());
}
builder.AppendLine();
}
}
catch (Exception ex)
{
// output any error
builder.AppendLine("**ERROR: " + ex.Message + "**");
}
}
}
catch (Exception ex)
{
// output any error
builder.AppendLine("**ERROR: " + ex.Message + "**");
}

// push to Console stream if we've got something to show
if (hasEntriesToShow)
Console.Write(builder.ToString());
}



You can call this directly, or use a directory traversal to output all enum values in all assemblies in a directory.

This example will output into a format which can be used on a Wiki page, but you can edit it to output in any format you like.

Posting Code on blogger.com

Wish I'd known how to post code on this blog before. I've manually spaced code out before, and it was so tedious it took multiple tries as I just go so bored with it.

Thanks Neil

Friday, April 20, 2007

AdoNetAppender in log4net

I've been running tests recently that required a quite detailed look into log files that log4net generates as part of our logging framework. Currently we have a number of Appenders loaded, such as RollingFileAppender, to log to different places.

However, a text file isn't always that easy to search through. Finding 1 separate entry is fine, but you can't list all of the error logs you have in the file, and you can't just show all messages that contain a particular string or string pattern. You could do this if these log entries were in a database table.

So as a little test I loaded in an AdoNetAppender after setting up a test database table to log to. I just used the config example as a base, and started logging.

That was all I really needed to do, I was impressed with how easy it was. It simplified the searches that I needed to do no end, and it would be a pretty easy task to tack an ASP.Net front end onto it to work as a log reader.

The Appender is very flexible, only taking a SQL statement to execute and a number of parameters to pass into it. The example config entry gives you pretty much everything you need, except maybe the machine name where the log entry came from.

If you do need this then it is relatively easy to add, due to the Appender's flexibility. Just add a column to the database (I've called it MachineName), and change the SQL statement to pass in a @machineName parameter.

Then in the parameters list, put something like this:

<parameter>
  <parameterName value="@machineName" />
  <dbType value="String" />
  <size value="50" />
  <layout type="log4net.Layout.PatternLayout">
      <conversionPattern
            value="%property{log4net:HostName}" />
  </layout>
</parameter>


That's all you need to log the machine name where the log originated.