Click here to Skip to main content
Click here to Skip to main content

Tagged as

11 Useful Classes You'll Love

, 18 Jun 2011 Ms-PL
Rate this:
Please Sign up or sign in to vote.
Impersonating Windows user (and "fun" bugs you can have with it), correctly disposing a WCF CommunicationObject, getting a property name from an expression, getting a relative path, weak collection listener, thread safe dictionary, enum flag help, test helper

Introduction

These utility classes are pieces of code I gathered from the internet during the past years. And I'm sure you'll find classes you'll use everyday here.

My goal is not to create a library, but just to gather cool pieces of code at the same place so people can use them by copy pasting, without any dependencies.

If that's not already the case, I highly recommend you to gather cool pieces of code you see on the web and have your personal framework correctly saved in a code repository somewhere. It will save you lots of time.

Some of you will say that you don't have to reinvent the wheel, and that's right.

But the point is that sometimes you have very specific and simple (but not easy) tasks to do and don't want the burden of yet another library. Moreover, you are the most likely person who will want to reuse these classes later: you already know where to find them, how they behave, what pitfalls they have, and what you learnt by using them.

I've kept the original comments in the code, so sometimes, you will be able to find the original author.

I want to thank people who shared these classes on the net, and who saved me lots of time and money. The best thing I can do is to spread their work.

All unit tests or code snippets presented here pass.

Table of Contents

11 Useful Classes

LogonUser: How to impersonate a user, the easy way

Sometimes, you will need to run a piece of code with the windows credential of another user to use his ACL rights. This is called impersonation. Here is an example.

[TestMethod]
public void CanUndoImpersonation()
{
	var oldName = Impersonation.CurrentUserName;
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.ShouldContains
			(TestUser.UserName, Impersonation.CurrentUserName);
		AssertEx.ShouldNotContains(TestUser.UserName, oldName);
	}
	AssertEx.ShouldContains(oldName, Impersonation.CurrentUserName);
}

Where Impersonation.CurrentUserName is:

public static String CurrentUserName
{
	get
	{
		return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
	}
}

Pitfalls to be aware of

Some "funny" bugs I have learnt the hard way and to be aware of...

[TestMethod]
public void LazyAssemblyInAImpersonatedSecurityContextWithoutFileRightsThrows()
{
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.Throws<FileLoadException>(() =>
		{
			Class1 hello = new Class1();
		});
	}
}

In this piece of code, the code throws because Class1, which is in another assembly, is loaded when the lambda expression inside AssertEx.Throws is "jitted". Which is... under TestUser's credentials who does not have read right on the assembly file!

This code works fine:

[TestMethod]
public void LoadAssemblyBeforeImpersonatingSoYouDontLazyLoadInTheWrongSecurityContext()
{
	Class1 test = null;
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.DoesntThrow(() =>
		{
			Class1 hello = new Class1();
		});
	}
}

But I have another surprise for you, and I suspect it's a bug of the .NET Framework (not sure if it's by design).

If you tried to load an assembly first on behalf of a user without the read right on it, then you'll never be able to load it later.

[TestMethod]
public void AndYouCantEvenRetryToLoadAssemblyInTheRightContext()
{
	var oldAccount = Impersonation.CurrentUserName;
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.Throws<FileLoadException>(() =>
		{
			Class1 hello = new Class1();
		});
	}
	Assert.AreEqual(oldAccount, Impersonation.CurrentUserName);
	AssertEx.Throws<FileLoadException>(() =>
	{
		Class1 hello = new Class1();
	});
}

I've seen that when I saw that my two previous tests would not pass when I run them at the same time...

PathUtil: How to get a relative path from an absolute folder

This task is really simple... but not easy to code! Here is how you can use it.

[TestMethod]
public void CanGetRelativePath()
{
	var path = PathUtil.RelativePathTo(@"c:\toto\titi", @"c:\toto\titi\tutu.txt");
	Assert.AreEqual("tutu.txt", path);
	path = PathUtil.RelativePathTo(@"c:\toto\tata", @"c:\toto\titi\tutu.txt");
	Assert.AreEqual(@"..\titi\tutu.txt", path);
}

How cool is that? But be careful to use "\" and not "/" in the path... you have the code if you want to fix that.

LambdaExtensions: Extension methods to extract a property name from an expression

This one is about avoiding magic string of property name in your code, so you don't have stupid error after refactoring.

[TestMethod]
public void CanGetPropertyName()
{
	TestClass test = new TestClass();
	var propertyName = LambdaExtensions.GetPropertyName(() => test.ReferenceMember);
	Assert.AreEqual("ReferenceMember", propertyName);
	propertyName = LambdaExtensions.GetPropertyName(() => test.ValueMember);
	Assert.AreEqual("ValueMember", propertyName);
}

NotifyPropertyChangedBase: A concrete use case of LambdaExtensions

If you are doing some WPF or Silverlight development, I'm sure you appreciate how to declare a property of a ViewModel with a code snippet:

public class ViewModel : NotifyPropertyChangedBase
{
	private int _Value;
	public int Value
	{
		get
		{
			return _Value;
		}
		set
		{
			if(value != _Value)
			{
				_Value = value;
				OnPropertyChanged(() => this.Value);
			}
		}
	}
}

And here is the test to be sure it works correctly as expected:

[TestMethod]
public void TypedOnPropertyChangedFireCorrectly()
{
	ViewModel vm = new ViewModel();
	bool fired = false;
	vm.PropertyChanged += (s, a) =>
	{
		Assert.AreEqual("Value", a.PropertyName);
		fired = true;
	};
	vm.Value = 5;
	Assert.IsTrue(fired);
}

Not convinced? How do you think about firing easily raising PropertyChanged upon another dependant property? See the constructor!

public class ViewModel : NotifyPropertyChangedBase
{
	public ViewModel()
	{
		this.AddDependency(() => this.Value, () => this.CalculatedValue);
	}
	private int _Value;
	public int Value
	{
		get
		{
			return _Value;
		}
		set
		{
			if(value != _Value)
			{
				_Value = value;
				OnPropertyChanged(() => this.Value);
			}
		}
	}

	public int CalculatedValue
	{
		get
		{
			return Value + 5;
		}
	}
}

And the test :

[TestMethod]
public void DependantPropertyFireCorrectly()
{
	ViewModel vm = new ViewModel();
	bool fired = false;
	vm.PropertyChanged += (s, a) =>
	{
		if(a.PropertyName == "CalculatedValue")
			fired = true;
	};
	vm.Value = 5;
	Assert.IsTrue(fired);
}

DisposableWrapperExtension: How to dispose effectively a WCF CommunicationObject

You are old enough to know how to use the IDisposable interface, you say? So what do you think about that.

[TestMethod]
public void WCFDisposableProblem()
{
	ServiceHost host = new ServiceHost(new TestService());
	var endpoint = host.AddServiceEndpoint(typeof(ITestService), 
			new WSHttpBinding(), "http://localhost:8372/");
	host.Open();
	var client = new ChannelFactory<ITestService>(endpoint).CreateChannel();
	bool throwAtTheEndOfUsing = false;
	AssertEx.Throws<EndpointNotFoundException>(() =>
	{
		using(((IClientChannel)client))
		{
			client.DoStuff();
			host.Close();
			throwAtTheEndOfUsing = true;
		}
	});
	Assert.IsTrue(throwAtTheEndOfUsing);
}

Here we close the ServiceHost before the client channel, so the client channel throws an exception inside the Dispose method instead of just aborting...

I swear that when you discover this behavior for the first time, the only thing you want is to stop programming and just start gardening potatoes in the campaign for the end of your life...

So to keep your pride and love as a developer, use DisposableWrapperExtension, here is how, thanks to a stackoverflow guru.

[TestMethod]
public void CanUseFixDisposable()
{
	ServiceHost host = new ServiceHost(new TestService());
	var endpoint = host.AddServiceEndpoint(typeof(ITestService), 
			new WSHttpBinding(), "http://localhost:8374/");
	host.Open();
	var client = new ChannelFactory<ITestService>(endpoint).CreateChannel();
	using(((IClientChannel)client).FixIDisposable())
	{
		client.DoStuff();
		host.Close();
	}
}

It Disposes, then Aborts the channel inside a ThreadPool's thread, so an exception will not crash your AppDomain. (Something I learnt the hard way too...)

EnumExtensions: How to easily manipulate a flag enum

If boolean arithmetic is not for you, then here is a simple class to manipulate flag enums, for example, with this enum:

[Flags]
public enum ErrorTypes
{
	None = 0,
	MissingPassword = 1,
	MissingUsername = 2,
	PasswordIncorrect = 4
}

You can easily see which flag is on or off :

[TestMethod]
public void CanAppendRemoveAndConsultFlagEnum()
{
	ErrorTypes error = ErrorTypes.MissingPassword;
	Assert.IsTrue(error.Has(ErrorTypes.MissingPassword));
	error = error.Append(ErrorTypes.MissingUsername);
	Assert.IsTrue(error.Has(ErrorTypes.MissingPassword));
	Assert.IsTrue(error.Has(ErrorTypes.MissingUsername));
	Assert.IsTrue(error.Has(ErrorTypes.MissingPassword.Append
				(ErrorTypes.MissingUsername)));
	error = error.Remove(ErrorTypes.MissingPassword);
	Assert.IsFalse(error.Has(ErrorTypes.MissingPassword));
	Assert.IsTrue(error.Has(ErrorTypes.MissingUsername));
}

ThreadSafeDictionary: How to add an item automatically, the easy way

A threadsafe Dictionary where you can automatically add/replace or remove items (You don't need to call ContainsKey before).

[TestMethod]
public void CanDeleteAndRemoveItems()
{
	ThreadSafeDictionary<int, string> dictionary = 
				new ThreadSafeDictionary<int, string>();
	dictionary.MergeSafe(1, "hello");
	dictionary.MergeSafe(2, "hello2");
	Assert.AreEqual(2, dictionary.Count);
	dictionary.RemoveSafe(3);
	dictionary.RemoveSafe(2);
	Assert.AreEqual(1, dictionary.Count);
	Assert.IsTrue(dictionary.ContainsKey(1));
}

The dictionary can be shared between threads safely.

BlockingStream: How to easily mock a client/server communication with a single Stream

This one, found on StackOverflow, will save your time in unit testing... Especially when you want to simulate client/server (consumer/producer) interaction without any dependency on Socket, WCF, System.Net, or Remoting.

[TestMethod]
public void CanWriteThenRead()
{
	BlockingStream stream = new BlockingStream();
	stream.WriteByte(5);
	var value = stream.ReadByte();
	Assert.AreEqual(5, value);
}
[TestMethod]
public void CanTimeout()
{
	BlockingStream stream = new BlockingStream();
	stream.ReadTimeout = 500;
	Stopwatch watcher = new Stopwatch();
	watcher.Start();
	var value = stream.ReadByte();
	watcher.Stop();
	Assert.IsTrue(500 < watcher.ElapsedMilliseconds);
	Assert.AreEqual(-1, value);
}

WeakCollectionChangedListener: How to stop memory leakage when a listener has a shorter life span than the listened object.

SpyObseravableCollection is a class which implements INotifyCollectionChanged, and is used to make my tests easier to read.

[TestMethod]
public void ListenerCanBeGarbageCollected()
{
	var listener = new SpyCollectionListener();
	var source = new SpyObservableCollection();
	WeakCollectionChangedListener weakListener = 
			new WeakCollectionChangedListener(source, listener);
	source.Add(4);
	listener.AssertCollectionChanged();
	WeakReference listenerHandle = new WeakReference(listener);
	listener = null;
	GC.Collect();
	Assert.IsFalse(listenerHandle.IsAlive);
	source.Add(6); //The weak listener unsubscribe on the next event
	source.AssertHasNoListener();
}

WeakObservableCollection: A concrete use case, a wrapper around the listened object and owned by the listener

The WeakCollectionChangedListener is not really hard to use, however I have another solution easier to read.

I just wrap the source collection inside a WeakObservableCollection. When the WeakObservableCollection is garbage collected, all his listeners will unsubscribe from the source collection.

[TestMethod]
public void 
  ListenerOfWeakObservableCollectionCanBeGarbageCollectedWhenWeakCollectionCollected()
{
	var source = new SpyObservableCollection();
	var wrappedSource = new WeakObservableCollection<int>(source);
	var listener = new SpyCollectionListener();
	wrappedSource.CollectionChanged += listener.OnCollectionChanged;
	source.Add(4);
	listener.AssertCollectionChanged();
	WeakReference listenerHandle = new WeakReference(listener);
	listener = null;
	wrappedSource = null;
	GC.Collect();
	Assert.IsFalse(listenerHandle.IsAlive);
	source.Add(6); //The weak listener unsubscribe on the next event
	source.AssertHasNoListener();
}

AssertEx: A class to make your tests readable

I used this class in my article, sorry about this one, I'm too lazy to write a test about tests (The meta test!) so I'll just remind you where I've used this class in my article.

For example, AssertEx.DoesntThrow:

[TestMethod]
public void LoadAssemblyBeforeImpersonatingSoYouDontLazyLoadInTheWrongSecurityContext()
{
	Class1 test = null;
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.DoesntThrow(() =>
		{
			Class1 hello = new Class1();
		});
	}
}

You may ask: What is the point of this method? Especially when you see what the implementation is.

public static void DoesntThrow(Action action)
{
	action();
}

There are two reasons:

First, it shows the user exactly what behavior I'm expecting. So that she/he will not give too much attention to the less important like Impersonation.Impersonate(TestUser.UserName, TestUser.Password).

Second, in this specific case, using a lambda expression could alter the result. Remember that in the test just before this one, using a lambda caused the loading of Class1's assembly during the security context of TestUser.

[TestMethod]
public void LazyAssemblyInAImpersonatedSecurityContextWithoutFileRightsThrows()
{
	using(Impersonation.Impersonate(TestUser.UserName, TestUser.Password))
	{
		AssertEx.Throws<FileLoadException>(() =>
		{
			Class1 hello = new Class1();
		});
	}
}

AssertEx.Throws assert that your lambda is throwing the right exception.

Conclusion: What utility classes do you own and use frequently?

Hope you'll like it, but I'm curious about you. What are your best personal utility classes ?

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Nicolas Dorier
Software Developer Freelance
France France
I am a trainer and a curious developer.
 
CEO of AO-IS, we created a tool to make IaaS on Azure more easy IaaS Management Studio.
 
If you are interested for working with me, for fun coding stuff, for freelance stuff, or interested in using our cloud training infrastructure freely for a kickass presentation for the dev community ? this way Smile | :)

Comments and Discussions

 
QuestionHow can I pass Current User LDAP to DB PinmemberManjunathabe01121-Mar-12 20:55 
AnswerRe: How can I pass Current User LDAP to DB PinmemberNicolas Dorier21-Mar-12 23:03 
QuestionExcellent Work PinmemberWhiteKnight14-Oct-11 9:45 
AnswerAssembly Re-Loading Comment PinmemberHexxellor15-Jul-11 17:33 
GeneralRe: Assembly Re-Loading Comment PinmemberNicolas Dorier15-Jul-11 21:44 
GeneralLambdaExtensions.GetPropertyName and Array.Length Pinmemberkornman0021-Jun-11 12:10 
GeneralRe: LambdaExtensions.GetPropertyName and Array.Length PinmemberNicolas Dorier21-Jun-11 12:48 
QuestionEnumExtensions lead to boxing Pinmemberkornman0019-Jun-11 19:46 
AnswerRe: EnumExtensions lead to boxing PinmemberNicolas Dorier19-Jun-11 23:30 
GeneralConcurrentDictionary PinmemberJohn Adams18-Jun-11 14:35 
GeneralRe: ConcurrentDictionary PinmemberNicolas Dorier18-Jun-11 14:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 18 Jun 2011
Article Copyright 2011 by Nicolas Dorier
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid