Mike Woodring's .NET Sample Page

This page contains sample code I've written to demonstrate various things on the .NET platform. If you have specific questions about any of these samples, you can email me at mike@bearcanyon.com.

If you have general questions about .NET that aren't specifically about the code in my samples, please do not email me. Instead, search the archives of DevelopMentor's public mailing lists. Most of the topics on this page are discussed on the DOTNET-CLR list. And because numerous very sharp people participate on this list, you're more likely to get a quick response to your question. Please just be sure to check the archives first to avoid posting something that's been asked and answered already.

All of this code is provided as-is with no warranty as to its usefulness or safety implied. Use at your own risk, etc., etc. That said, you're free to use this source in your own production software, but you are not permitted to redistributed the source code itself.

Remoting and Sockets
    Socket Connection Limit Test Utility
    Custom RealProxy Providing Automatic Thread Synchronization
    IdentitySink Remoting Channel Sink
    IdentitySink Remoting Channel Sink (Programmatic Configuration)
    OneWayAttribute Sample
    Using IIS/ASP.NET to Host .NET Remoting Servers
    Remoting Events
    Marshaled ObjRef Demo
    Synchronous & Asynchronous Sockets
    Firing Events from Remoting Servers
    Unregistering Client-Activated and Well-Known Service Type Entries

Reflection
    AppDomain BaseDirectory (APPBASE) Modification
    Assembly Statistics Utility
    The DynoIndexer
    CallOnLoadAttribute
    Serializable Utility
    AttributeUsage Utility

Threading and Synchronization
    QueuedBackgroundWorker Component
    Passing UserState to a BackgroundWorker.RunWorkerCompleted Event Handler
    Custom Thread Pool
    Supporting the Fire-and-Forget Idiom for Asynchronous Delegates Without Leaking
    CPU Stress Testing Utility
    Custom RealProxy Providing Automatic Thread Synchronization
    ThreadWaitHandle Class
    Thread Pool Control Sample
    Supporting the Synchronized Idiom
    Updating WinForm Controls From Different Threads of Execution
    Another Demonstration of Updating WinForm Controls From Different Threads of Execution
    Deferred Procedure Call (DPC) Queue Object

Assemblies
    Parsing PE File Headers to Determine if a DLL or EXE is an Assembly
    Programatically Enumerate the global, download, and native assembly caches
    Side-by-side assembly support without using the GAC
    Publisher Policy Sample

Security
    Digital Signature Generation
    StrongNameIdentityPermission
    Generate token for public key in text format

Configuration
    Arbitrary Configuration File Parser
    Per-Assembly Configuration Files
    Registering Trace Listeners
    Custom Configuration Section Handler

Context
    Using Custom Context Attributes to Build Interception-Based Services
    TraceHook.net
    Automatic Performance Counters

Miscellaneous
    TinyURL Utility
    Using LoadLibrary and GetProcAddress from C#
    Simulating Parameterized Named Properties in C#
    ICorPublishProcess, ICorPublishAppDomain Interop Shims
    Serialization & Transient Data
    IDataReader Process Snapshot Sample
    Logging HTTP Module
    DirectConsole Class


Remoting and Sockets Samples

Socket Connection Limit Test Utility
Languages: C#
CLR Version: V1
Description:

This utility consists of a client and server Windows Forms application that uses the .NET socket classes to test the limits of a given machine's ability to accept or make socket-based connections. Refer to the enclosed readme.htm file for more details.


Custom RealProxy Providing Automatic Thread Synchronization
Languages: C#
CLR Version: V1
Description:

This sample provides a custom RealProxy that can be used to guarantee single-threaded access to arbitrary MarshalByRefObject-compatible objects. The proxy can be dynamically 'wrapped' around existing references to MarshalByRefObject-derived objects, or installed automatically by applying the provided ThreadSafeProxyAttribute attribute to any ContextBoundObject-derived type.


IdentitySink Remoting Channel Sink
Languages: C#
CLR Version: V1
Description:

This sample demonstrates how to write a custom channel sink (both client- and server-side) that captures the client thread principal, transmits it, and restores it on the server-side thread handling a remote method call. This sink does not provide any extra measure of security - just extra information. It's important to realize the vulnerabilities that are possible using this kind of sink, so if you download this sample, be sure to read the enclosed README.HTM file before using the code in a production system.


IdentitySink Remoting Channel Sink (Programmatic Configuration)
Languages: C#
CLR Version: 1.1
Description:

This is the same sample as the Identity Remoting Channel Sink above, but tweaked to demonstrate client-side configuration of the remoting channel and sinks programmatically instead of using a configuration file.


OneWayAttribute Sample
Languages: C#
CLR Version: RC1
Description:

This sample demonstrates the OneWayAttribute remoting attribute. Specifically, it demonstrates how the attribute does not affect intra-appdomain calls, but does affect calls that go through message sinks.

To test:

o Unzip to a dir of your choice.
o Open a cmd shell in that dir.
o Use nmake to build.
o Execute "start server" to launch a server process.
o Execute "client" to run the client process.


Using IIS/ASP.NET to Host .NET Remoting Servers
Languages: C#
VB.NET
CLR Version: RC1
Description:

This sample demonstrates using IIS/ASP.NET to host a CLR object using .NET remoting. The sample uses both kinds of WellKnown service types (singleton and singlecall) as well as a client-activated type. This sample also demonstrates using the standard http channel/soap formatter combination as well as the more compact, but still firewall friendly, http channel/binary formatter combination.


Remoting Events
Languages: C#, VB.NET
CLR Version: 1.1, 2.0
Description:

This sample demonstrates the how to use events in a .NET remoting scenario so that the server process does not need access to the client assembly at run-time. Demonstrates the use of a shim class for forwarding the delegate invocation used to fire the event.

Refer to the comments in client.cs or client.vb for details.


Marshaled ObjRef Demo
Languages: C#
CLR Version: Beta 2
Description:

Demo that uses the SOAP formatter to serialize an objref to disk, which can then be transferred across the Internet using any technology (MSN Messenger, email, etc), deserialized, and used to make a method call back to the original object.

Unzip the source to a directory then build using nmake. Run the exporter.exe on one machine, which will create soapobjref.txt. Send that file to another person that also has the demo built. Place that file in the directory where importer.exe resides, then run importer. A message should be displayed on the server's console.


Synchronous & Asynchronous Sockets
Languages: C#
CLR Version: V1
Description:

Contains a client and two versions of a string echo server. One server can only handle one client at a time. The other server demonstrates the use of asynchronous I/O in order to handle multiple connected clients in an overlapped manner.


Firing Events from Remoting Servers
Languages: C#
CLR Version: 1.0, 1.1
Description:

When server-side remoting components fire events (and when not using [OneWay] decorated event delegates) they are making a synchronous call to each registered client. If any of these clients disconnects from the server without first unregistering, or is otherwise unreachable, an exception will result in the server at the point where the event is fired. Furthermore, iteration over the list of registered clients will be terminated before the remaining clients can be notified of the event.

If the thread that fires this event is one of your own threads, then your thread will be terminated if not properly handled. But at least you'll know you have a problem.

More typically, however, the thread that fires the event is not 'yours', but rather a pooled thread that was used to process an incoming remote method invocation, or maybe a timer tick event. In either case, the runtime will have provided a top-level exception handler that either throws the exception away (as with a timer) or marshals the exception back to the client (as when a remote method invocation caused the event to fire). In the former case, you may not even realize you have a problem, other than by virtue of the fact that your timer-related functions cease. In the latter case, the poor client that triggered the event firing will receive an exception as a result of your failed attempt to fire the event.

No matter what the scenario may be, firing events from server-side code is something that should be treated with great care. Luckily, it is fairly easy to take proper defensive precautions - you just need to know how.

The basic idea is fairly simple - iterate over the list of registered clients, calling each individually (using GetInvocationList). Catch any exceptions that might result. If an exception occurs calling a particular client, remove them from the list of registered clients. The only other dimension is to do all of this in a thread-safe fashion so that your code to unregister clients doesn't interfere with clients making remote method calls to your server to do the same.

The sample code below demonstrates the pattern a server-side piece of remoting code can use to take these precautions:

public class SomeServerClass : MarshalByRefObject
{
    // _OnFoo holds list of registered clients for OnFoo event.
    // _eventLock is an object used to synchronize multithreaded
    // access to _OnFoo.  A separate object is used because
    // (a) _OnFoo is initially null and (b) might change over time
    // as clients are registered and unregistered.
    //
    private EventHandler _OnFoo;
    private object _eventLock = new object();

    // OnFoo - the publicly visible event.
    //
    public event EventHandler OnFoo
    {
        // The add/remove operations are performed while
        // holding the lock on the private _OnFoo field.
        //
        add {
            lock( _eventLock ) {
                _OnFoo += value;
            }
        }

        remove {
            lock( _eventLock ) {
                _OnFoo -= value;
            }
        }
    }

    public void SomeCodeThatFiresEvents()
    {
        EventHandler[] clients;

        // Grab the list of registered clients in a thread-safe
        // fashion by first acquiring the lock on the _eventLock
        // field (sychronizing with any calls to the OnFoo
        // add/remove handlers above).
        //
        lock( _eventLock ) {
            clients = _OnFoo.GetInvocationList();
        }

        // Iterate through the list of clients, unregistering any that can
        // no longer be reached.
        //
        foreach( EventHandler client in clients ) {
            try {
                client(this, EventArgs.Empty);
            }
            catch {
                // Call our thread-safe OnFoo remove handler to
                // remove this client from the list of registered clients.
                //
                OnFoo -= client;
            }
        }
    }
}

With the above pattern, if the callback to a given client fails for any reason, the delegate referring to that client will be removed from the list of registered clients. This has two effects: allowing the server-side code to continue firing the event callback to clients that were registered after the 'bad' client, and eliminating the needless timeout the next time this event is fired by removing the offending client from the list.


Unregistering Client-Activated and Well-Known Service Type Entries
Languages: C#
CLR Version: 1.0, 1.1
Description:

This source file defines a helper class called RemotingConfigurationHelper that provides methods for unregistering previously registered client-activated and well-known service types (counterparts to RemotingConfiguration.RegisterWellKnownServiceType and RemotingConfiguration.RegisterActivatedServiceType).


back to top

Reflection Samples

AppDomain BaseDirectory (APPBASE) Modification
Languages: C#
CLR Version: 1.1
Description:

This sample demonstrates how to modify This sample demonstrates how to modify an existing AppDomain's BaseDirectory property so that assembly resolution can be influenced on the fly. Using the class included in this sample, it looks something like this:

AppDomainUpdater appDomainUpdater = new AppDomainUpdater(AppDomain.CurrentDomain);
appDomainUpdater.BaseDirectory = @"c:\SomeOtherDirectory";
    


Assembly Statistics Utility
Languages: C#
CLR Version: V1
Description:

This sample/utility demonstrates some very simple use of reflection for compiling statistics on the types contained in a given assembly, or all assemblies in a given directory (optionally including all its subdirectories).

Example usage:

C:\Program Files\Microsoft Visual Studio .NET> asmstats . /r
[progress messages omitted]
Processed 581 assemblies comprising 581 modules.

  Types:         5,325 (of any kind)
    Classes:     3,182 (1,400 public)
    Attributes:  53 (13 public)
    Delegates:   486 (410 public)
    Interfaces:  1,124 (416 public)
    Enums:       372 (191 public)
    Value types: 108 (9 public)

  Members:       516,096 (of any kind, instance and static)
    Methods:     369,648 instance, 2,415 static
    Events:      29,253 instance, 10 static
    Properties:  62,764 instance, 94 static
    Fields:      16,429 instance, 35,483 static


The DynoIndexer
Languages: C#
CLR Version: Beta 2
Description:

This sample provides a sample of using the reflection APIs to get & set fields and properties, or invoke methods, on an arbitrary object instance. The sample class provided is called the DynoIndexer. The DynoIndexer is used along these lines:

using System;

class Point {
  private int x;
  private int y;
  public int XPos { get { return(x); } }
  public int YPos { get { return(y); } }
  public int Sum { return(x + y); }
}

class App {
  static void Main() {
    DynoIndexer di = new DynoIndexer(new Point(), true);
    di["x"] = 10;
    di["y"] = 20;
    Console.WriteLine("x = {0}", di["XPos"]);
    Console.WriteLine("y = {0}", di["YPos"]);
    Console.WriteLine("x + y = {0}", di["Sum"]);
  }
}

The above example uses the indexer to modify the x and y fields of a Point instance, invoke its XPos and YPos property getters, and invoke the Sum method.

The main intent of the DynoIndexer is to serve as sample code. However, it's actually pretty useful when writing code to spelunk around various parts of the system.


CallOnLoadAttribute
Languages: C#
CLR Version: V1
Description:

This sample demonstrates how to use the AppDomain.AssemblyLoad event to hook assembly load notifications and, if the newly loaded assembly has been annotated with one or more instances of the CallOnLoad attribute, have one or more methods automatically invoked.

Call-on-load processing has to be enabled with a single call to the static CallOnLoadAttribute.Enable method - no processing occurs until this has been invoked in a given AppDomain. This method optionally allows you to request that call-on-load processing be performed for assemblies that have already been loaded into the AppDomain at the time Enable has been called.


Serializable Utility
Languages: C#
CLR Version: Beta 2
Description:

Utility that takes an assembly name and type name as input and prints out an indication as to whether or not the specified type is Serializable, and whether or not the type implements the ISerializable interface or the IDeserializationCallback interface. Here's a sample of the output produced:

c:\>sa mscorlib System.Collections.Hashtable
System.Collections.Hashtable is serializable
  Implements ISerializable
  Implements IDeserializationCallback

AttributeUsage Utility
Languages: C#
CLR Version: Beta 2
Description:

Utility that takes an assembly name and type name of an attribute as input and prints out the AttributeUsage characteristics for that attribute. Here's a sample of the output produced:

c:\>au mscorlib Serializable
Hierarchy:     SerializableAttribute : Attribute
Valid on:      Class, Struct, Enum, Delegate
AllowMultiple: False
Inherited:     False

back to top

Threading and Synchronization Samples

QueuedBackgroundWorker Component
Languages: C#
CLR Version: CLR 2.0
Description:

This sample program demonstrates a knock off of the System.ComponentModel.BackgroundWorker class I call QueuedBackgroundWorker. Like BackgroundWorker, this component supports a RunWorkerAsync method, and associated progress and completion methods and event notifications. But unlike BackgroundWorker, this component supports overlapping calls to its RunWorkerAsync method, allowing callers to queue up multiple operations for sequential execution by a background thread.

The implementation of the QueuedBackgroundWorker component included in this sample was written from the ground up so as to serve as an example of how to implement the event-based asynchronous pattern in your own components.

If you grab this code, be sure to read all of the comments at the top and bottom of QueuedBackgroundWorker.cs and QueuedBackgroundWorkerWithoutAbusingConstructorInfo.cs before using the QueuedBackgroundWorker component in your own code. The following entries in my blog will provide additional information: here, here, and here.


Passing UserState to a BackgroundWorker.RunWorkerCompleted Event Handler
Languages: C#
CLR Version: CLR 2.0
Description:

This sample program demonstrates one possible work around for the fact that the RunWorkerCompletedEventArgs.UserState property always returns null, regardless of how BackgroundWorker.RunWorkerAsync was called. The original write up on the issue can be found in my blog. This blog post provides the follow up and further explains this sample. Refer to the comments through the source included with this sample for more details.


Custom Thread Pool
Languages: C#
CLR Version: V1
Description:

This sample provides a custom implementation of a managed thread pool. The thread pool supports the following features:

* Instrumented with numerous performance counters.
* Can be explicitly started and stopped (and restarted).
* ThreadPool class extends WaitHandle (pool is signalled when all threads exit after a Stop operation)
* Configurable thread priority for threads.
* Configurable foreground/background characteristic for threads.
* Configurable thread base names.
* Support for cancelling pending operations.
* Configurable minimum thread count.
* Configurable maximum thread count.
* Configurable dynamic thread trigger.
* Configurable dynamic thread decay.
* Configurable limit to request queue size (default is unbounded).
* Optional propogation of calling thread's call context.
* Optional propogation of calling thread's security principal.
* Optional propogation of calling thread's HTTP context.
* Support for started/stopped event notification.


Supporting the Fire-and-Forget Idiom for Asynchronous Delegates Without Leaking
Languages: C#
CLR Version: 1.0, 1.1
Description:

Starting with the 1.1 release of the .NET Framework, the SDK docs now carry a caution that mandates calling EndInvoke on delegates you've called BeginInvoke on in order to avoid potential leaks. This means you cannot simply "fire-and-forget" a call to BeginInvoke without the risk of running the risk of causing problems.

This sample provides an AsyncHelper class with one public method called FireAndForget that is intended to support the fire-and-forget idiom without the fear of leak. The usage model is that instead of calling BeginInvoke against a delegate, you would instead call AsyncHelper.FireAndForget, passing that delegate and it's parameters as input.

For example, assuming a delegate defined as follows:

    delegate void CalcAndDisplaySumDelegate( int a, int b );
Instead of doing this to fire-and-forget an async call to some target method:
    CalcAndDisplaySumDelegate d = new CalcAndDisplaySumDelegate(someCalc.Add);
    d.BeginInvoke(2, 3, null);
You would instead do this:
    CalcAndDisplaySumDelegate d = new CalcAndDisplaySumDelegate(someCalc.Add);
    AsyncHelper.FireAndForget(d, 2, 3);


CPU Stress Testing Utility
Languages: C#
CLR Version: V1
Description:

This is the C#/WinForms version of a CPU stress testing utility I wrote a few years ago in C++/MFC. The utility provides a simple slider bar user interface that allows you to place an arbitrary load on the processor(s) in your system. Automatically detects and handles multiple processors.


Custom RealProxy Providing Automatic Thread Synchronization
Languages: C#
CLR Version: V1
Description:

This sample provides a custom RealProxy that can be used to guarantee single-threaded access to arbitrary MarshalByRefObject-compatible objects. The proxy can be dynamically 'wrapped' around existing references to MarshalByRefObject-derived objects, or installed automatically by applying the provided ThreadSafeProxyAttribute attribute to any ContextBoundObject-derived type.


ThreadWaitHandle Class
Languages: C#
CLR Version: V1
Description:

This file contains a class called ThreadWaitHandle that is a derivative of System.Threading.WaitHandle and that can be used to perform WaitHandle.Wait* operations on thread objects. The purpose of the code is to allow a programmer to create one or more threads and then, at some later point, block until that thread exits.

Note - due to the nature of the implementation, this code is highly coupled to the build of the CLR that the code was developed and tested on. Be sure to read the comments in ThreadWaitHandle.cs for a more detailed explanation.


Thread Pool Control Sample
Languages: C#
CLR Version: V1
Description:

This sample demonstrates how to access and call the ICorThreadpool interface that's implemented in MSCOREE.DLL from a C# program in order to adjust the operating constraints of the CLR-managed thread pool for a given process. See the comments in tpcontrol.cs and ICorThreadPool.cs for details.


Supporting the Synchronized Idiom
Languages: C#
CLR Version: Beta 2
Description:

This sample demonstrates the idiom used by many classes in the framework (especially collection classes like ArrayList) for supporting just-thread-safe-enough access.

The general idea is that you don't want to make every class thread-safe internally and therefore always pay the associated performance penalty. Clients of your type that do not use your class in a multithreaded environment will pay a price without gaining any benefit. However, thread savvy programmers need a way to use your object in a thread-safe fashion. In the absence of any intrinsic support, clients can use the Monitor class to acquire and release the SyncBlock associated with your object instance. But most thread-aware classes provide a thread-safe, type-compatible wrapper that takes care of the thread-safety concerns internally. Such a wrapper is generally exposed by calling a Synchronized method on the object (or a static method on the type) that returns a new instance of a nested type that does the lock acquisition and releasing.

By supporting this usage, programmers that use your type in a thread safe environment can use your type directly as follows:

Foo f = new Foo();
// Use foo...
While programmers that use your type in a thread-hot environment can use your thread-safe wrappers as follows:
Foo f = Foo.Synchronized(new Foo());
// Use foo...
Or optionally like this:
Foo f = new Foo(); // Or retrieved from somewhere else...
f = f.Synchronized();
// Use foo...


Updating WinForm Controls From Different Threads of Execution
Languages: C#
CLR Version: V1
Description:

This piece of sample code demonstrates using Control.BeginInvoke to safely update WinForm controls from threads other than the thread that the control was created on.

Two scenarios are described: using a Timer object from the System.Threading namespace to periodically update a control; and using Delegate.BeginInvoke to perform some task asynchronously, and updating a control from the thread that performs the specified callback.


Another Demonstration of Updating WinForm Controls From Different Threads of Execution
Languages: C#
CLR Version: V1
Description:

This sample is an alternative demonstration of using Control.InvokeRequired that demonstrates both the problem as well as the solution. In that regard, it's slighly more educational than my other sample.


Deferred Procedure Call (DPC) Queue Object
Languages: C#
CLR Version: V1
Description:

This little sample demonstrates the use of what I call a "deferred procedure call (DPC) queue". The idea is similar to using the built-in CLR thread pool for performing work asynchronously to the thread issuing the request. However, only one thread ever services the request queue, thus ensuring the order of processing. In this way, you can use multiple instances of a DPC queue to tackle different tasks (potentially at a different priority).


back to top

Assemblies Samples

Parsing PE File Headers to Determine if a DLL or EXE is an Assembly
Languages: C#
CLR Version: 1.1
Description:

This sample demonstrates how to parse the PE headers of any valid Win32 Portable Executable (PE) file (DLL or EXE) to determine if that file is in fact a .NET assembly (as opposed to just a vanilla Win32 PE file). The technique I went with was to call the Win32 LoadLibraryEx function with the DONT_RESOLVE_DLL_REFERENCES flag to map the specified file into process memory. Then knowing that the HANDLE returned by LoadLibraryEx is actually a pointer to the base load address of the PE file in memory, I use C# pointer operations to 'walk through' the PE headers looking for a CLI header. As a result of using pointer syntax, any assembly that uses this code must be built to allow unsafe code blocks, which means it won't be verifiably type safe. So keep that in mind if you decide to use this code.

I didn't particularly need this code, but a DevelopMentor colleague of mine did, so here it is.


Programatically Enumerate the global, download, and native assembly caches
Languages: C#
CLR Version: V1
Description:

This sample defines and demonstrates the necessary Win32 and COM interop shims that allow an application to programmatically enumerate the contents of the global, download, and native assembly caches.


Side-by-side assembly support without using the GAC
Languages: C#
CLR Version: V1
Description:

This sample demonstrates how to use an application's configuration file and CODEBASE redirects to support the side-by-side installation and loading of multiple versions of the same assembly without requiring that the assemblies be installed into the GAC.

This sample builds 4 versions of the same library assembly, and then deploys them to different subdirectories of the APPBASE along these lines:

c:\...\sampledir
    app_1.0.0.0.exe
    app_1.2.3.4.exe
    app_2.0.0.0.exe
    app_3.0.0.0.exe
    \bin
        \1.0.0.0
            testlib.dll
        \1.2.3.4
            testlib.dll
        \2.0.0.0
            testlib.dll
        \3.0.0.0
            testlib.dll
Each application exe is built against the matching version of testlib.dll, which is deployed to a different subdirectory below the APPBASE. Due to the CODEBASE redirects in the application configuration file, running a particular version of the application results in the desired version of testlib.dll being loaded and used.

Refer to testlib.cs for instructions on how to build and run this sample.


Publisher Policy Sample
Languages: C#
CLR Version: Beta 2
Description:

This sample demonstrates how to create and deploy publisher policy for a strongly named assembly. The zip includes a readme.txt that indicates how to move through the sample step-by-step in order to see the effect of policy on assembly resolution at runtime.


back to top

Security Samples

Digital Signature Generation
Languages: C#
CLR Version: V1
Description:

This utility demonstrates the use of the SHA1Managed and RSACryptoServiceProvider classes to generate, sign, and verify signatures for arbitrary files. Useful when the data being signed need not be encrypted, but any changes to the data need to be detectable.


StrongNameIdentityPermission
Languages: C#
VB.NET
CLR Version: Beta 2
Description:

Demonstrates the use of the StrongNameIdentityPermission attribute with the SecurityAction.LinkDemand.


Generate token for public key in text format
Languages: C#
CLR Version: V1
Description:

Someone once asked if there was a way to generate the public key token for a given public key that's rendered in text form (for example, from an ILDASM display). For what it's worth, this program does just that.


back to top

Configuration Samples

Arbitrary Configuration File Parser
Languages: C#
CLR Version: V1
Description:

This sample contains a class called ConfigFileReader that allows you to process the appSettings key/value settings in arbitrary configuration files (not just the one that's automatically parsed for the running application). The ConfigFileReader class also allows you to process other key/value sections besides the standard appSettings area.


Per-Assembly Configuration Files
Languages: C#
CLR Version: V1
Description:

This sample contains a class called AssemblySettings that allows you to use per-assembly configuration files with appSettings-like configuration elements.

The usage model is that, for example, an assembly named foo.dll located in the c:\foo\bar\baz directory, a configuration file for that assembly name foo.dll.config can be placed in the same directory and accessed using the enclosed AssemblySettings class in the same fashion as normal appSettings items can for application configuration files.

If you know the keys you're after, the following access syntax is probably the most convenient:

AssemblySettings settings = new AssemblySettings();
string someSetting1 = settings["someKey1"];
string someSetting2 = settings["someKey2"];
If you want to enumerate over the settings (or just as an alternative approach), you can do this too:
IDictionary settings = AssemblySettings.GetConfig();

foreach( DictionaryEntry entry in settings )
{
    // Use entry.Key or entry.Value as desired...
}
In either of the above two scenarios, the calling assembly (the one that called the constructor or GetConfig) is used to determine what file to parse and what the name of the settings collection element is. For example, if the calling assembly is c:\foo\bar\baz\foo.dll, then the configuration file that's parsed is c:\foo\bar\baz\Foo.dll.config, and the configuration section that's parsed must be named <assemblySettings>.

To retrieve the configuration information for an arbitrary assembly, use the overloaded constructor or GetConfig method that takes an Assembly reference as input.


Registering Trace Listeners
Languages: C#
CLR Version: Beta 2
Description:

Illustrates how to register additional Trace listeners using an application configuration file.


Custom Configuration Section Handler
Languages: C#
CLR Version: Beta 2
Description:

This program demonstrates how to write and use a custom configuration section handler to parse user-defined sections of application configuration files (like <appSettings>). The sample handler provided is called the ElementNormalCfgHandler, and supports any element-normal configuration section to an arbitrary depth. For example, this handler can handle a section formatted as follows:

<myStuff>
    <day>Wednesday</day>
    <hour>11</hour>
    <author>
        <fname>Mike</fname>
        <lname>Woodring</lname>
        <stats>
            <age>19</age>
            <sex>male</sex>
        </stats>
        <otherStuff>
            <color>red</color>
            <yetMoreStuff>
                <fuzzy>true</fuzzy>
                <round>false</round>
            </yetMoreStuff>
        </otherStuff>
    </author>
</myStuff>

Once the ElementNormalCfgHandler assembly is registered in an application configuration file, the application can retrieve the information using ConfigurationSettings.GetConfig. Each element becomes a key. Elements with a simple text child contain a text value associated with that key. Elements with nested elements contain a dictionary value associated with that key. For example, the following would retrieve the root myStuff dictionary:

IDictionary myStuff = (IDictionary)
    ConfigurationSettings.GetConfig("myStuff");
The following would then retrieve the nested author information:
IDictionary authorInfo = (IDictionary)myStuff["author"]
And the following would retrieve the nested stats information:
IDictionary status = (IDictionary)authorInfo["stats"]


back to top

Context Samples

Using Custom Context Attributes to Build Interception-Based Services
Languages: C#
CLR Version: 1.0, 1.1
Description:

This sample demonstrates how to build a custom context attribute that installs an interceptor which looks for attributes applied to the target object's fields and methods to perform services. Two types of services are supported: inverting the case of characters in strings and reversing the character positions within strings. These services are requested by applying one or both of two custom attributes (ReverseStrings and InvertStringCase) to methods and/or fields of a type derived from ContextObjectObject that has the StringServices context attribute applied.

For example, the following class requests that all strings passed to the Bar method be reversed when Bar is called, and that the case of each character in the _baz field be inverted whenever any method is called:

[StringServices]
public class Foo : ContextBoundObject
{
    [InvertStringCase] private string _baz = "Foo Bar";
    
    [ReverseStrings]
    public void Bar( string s1, int x, string s2 )
    {
    }
}

Performing such processing using the type information on methods is a simple matter because each method call message passed to custom message sinks carries with it the necessary type information. But processing fields on the target object requires that the chain of message sinks leading from your custom message sink to the eventual target object be traversed in order to locate the target object whose method is being invoked. This sample demonstrates both techniques.

Gratuitous search terms: IContextAttribute, IContextProperty, IContributeObjectSink, IContributeServerContextSink, IMessageSink, object sink, server context sink, AOP, aspect-oriented programming.


TraceHook.net
Languages: C#
CLR Version: Beta 2
Description:

Like a few others, the first idea I had when I started exploring the context architecture was to provide an automatic method tracing facility. I haven't seen what others did, but this version uses a dynamic sink approach, which lets you "wrap" and "unwrap" the tracing facility around an object (or proxy to an object) as needed at runtime. Exactly what's traced (process id, thread id, context id, timestamp, etc.) is customizable via flags. Exactly where the trace messages our output is pluggable - just pass pass any Stream of your choosing when you install the interceptor (by default, output goes to stdout).


Automatic Performance Counters
Languages: C#
CLR Version: Beta 2
Description:

The second idea I had when looking into the context infrastructure was to be able to put an attribute on a class that caused some performance counters to be automatically created and published that could be monitored using PerfMon. This version is really crude, but does demonstrate the feasibility (although non-deterministic finalization makes things a little difficult in this case). Applying the attribute to a class results in four counters being published: Instance, Instances/sec, Calls, and Calls/sec. Counter instances are named "ProcessId AppDomainName ClassName", so you can monitor instances of the same type in different processes, or different app domains within a process.


back to top

Miscellaneous Samples

TinyURL Utility
Languages: C#
CLR Version: 1.1
Description:

This little utility grabs a URL from the clipboard, sends it to tinyurl.com to get/generate a tinyurl, and pastes the resulting tiny url back into the clipboard. Configure a desktop shortcut to this utility to launch when something like CTRL-SHIFT-T is pressed, and the entire long-to-tiny URL converstion process is as easy as CTRL-C, CTRL-SHIFT-T, CTRL-V!


Using LoadLibrary and GetProcAddress from C#
Languages: C#
CLR Version: 1.0, 1.1
Description:

This sample demonstrates how to write a C# program that supports "pluggable" native DLLs that conform to a required C-based API of exported functions. Since p/invoke declarations require compile-time knowledge of the DLL, they can't be used in a more dynamic environment where you know the names and signatures of the functions you want to call ahead of time, but not which DLL you're going to load and call into. This sample demonstrates how to work around p/invoke's limitations to support this scenario.

Refer to the comments at the tops of the included source code for more details.

Note, after working up this implementation, which I thought was pretty clever, I went searching to to see if anyone else had come up with this same solution. Sure enough, Richard Birkby has (and 1.5 years ago at that). So much for being original :-)

If you strip away everything in our code except for the x86 assembly language and the core concept (so ignoring the fluff of the surrounding test jigs we each wrote and the fact that I used a __declspec(naked) function in C with inline assembly, and he used the stand alone x86 assembler), our solutions are identical.

You can checkout Richard's version here:

http://www.codeproject.com/csharp/dyninvok.asp


Simulating Parameterized Named Properties in C#
Languages: C#
VB.NET
CLR Version: V1
Description:

Unlike VB.NET, C# does not support parameterized named properties (C# has indexers instead, which are the default/unnamed paremeterized property of a type). This sample demonstrates how to simulate parameterized named properties in C# suitable for in any managed language, but specifically for VB.NET clients that are accustomed to such a language feature.


ICorPublishProcess, ICorPublishAppDomain Interop Shims
Languages: C#
CLR Version: V1
Description:

This sample defines and uses several COM interop shims in C# for accessing the unmanaged ICorPublishProcess, ICorPublishAppDomain, et. al. family of interfaces for enumerating (un)managed processes and appdomains.


Serialization & Transient Data
Languages: C#
CLR Version: Beta 2
Description:

Demonstrates the use of [Serializable], [NonSerialized], and IDeserializationEventListener for performing local fixups of [NonSerialized] fields when deserialization occurs.


IDataReader Process Snapshot Sample
Languages: C#
CLR Version: RC1
Description:

This sample demonstrates implementing IDataReader by taking a snapshot of the list of running processes on an arbitrary machine and representing the result via the IDataReader interface. I'm no data access pro, but I wrote up this little sample to demonstrate how IDataReader can be used to polymorphically represent arbitrary data in tabular form.


Logging HTTP Module
Languages: C#
CLR Version: V1
Description:

This library provides a sample implementation of IHttpModule that logs HTTP request and response packets (whether for web pages or web services) to a log file on disk.


DirectConsole Class
Languages: C#
CLR Version: V1
Description:

Sample code that provides a DirectConsole shim class that uses P/Invoke to make most of the Win32 console API available to .NET programs.


back to top