The switches that ship with .NET will work fine for most cases. However, there are times when you may want to implement your own custom switches. Perhaps you want to migrate another system where you have a different logging strategy that worked and you want to mimic that strategy in .NET. What if the all-inclusive logic of the TraceSwitch didn't quite meet your needs?
I'll demonstrate how to create a custom switch. I designed my example to give you ideas of how you could implement your own custom switch to achieve the granularity and logic handling appropriate for your needs.
The custom switch in Listing 1
, FlagSwitch, creates new switch categories: None
, and Exception
. As opposed to the TraceSwitch where higher switch levels are all inclusive of lower levels, the FlagSwitch lets you turn categories on and off at will.
The FlagLevel enum is decorated with the [Flags]
attribute, allowing you to use it in bitwise operations. You can explicitly set each element with a hex value to ensure their values don't overlap.
Notice how my example exposes each switch setting as a property. The get
accessors use the SwitchSetting
of the base class, Switch, and use a bit-wise AND
operation to check if the bit representing that condition is set. The Switch class takes care of reading configuration file settings and ensures that the SwitchSetting
property is set accordingly. The implementation also ensures that in all properties, except for None
, the None
bit is turned off, since this would represent an illogical condition.
The configuration files in previous examples showed how to add a single switch to an application. You can do more with configuration files including add additional switches and remove switches. The following snippet shows these additional switch configuration capabilities:
<?xml version="1.0" encoding="utf-8" ?>
<add name="TraceSwitch3" value="4" />
<add name="TraceSwitch2" value="4" />
<add name="TraceSwitch1" value="4" />
<remove name="TraceSwitch2" />
The configuration file adds three switches, which you can use in different parts of an application to give you more control over where you want to view debug output. The remove
element essentially un-defines TraceSwitch2
, making any conditional Trace statements in your code evaluate to false
and not print. The remove
element provides a way to turn a switch off, which is an alternative to deleting, commenting, or setting a value to 0 (assuming that 0 represents a condition that prevents trace output) of an existing switch.
Dynamic Switch Settings
Besides using configuration files, you can change switch settings dynamically in code. For example, the following code modifies the TraceLevel setting to None
for a TraceSwitch:
switch1.Level = TraceLevel.Off;
If you needed to dynamically set the switch on a custom switch, you should provide a property that accepts an enum for the custom switch type. The implementation of that property can get and set base.SwitchSetting
appropriately. The following property implements this for the custom switch described in the Custom Switches section of this article:
public FlagLevel Level
base.SwitchSetting = (int)value;
This is necessary because the Switch.SwitchSetting
property has protected visibility.