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.
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;
}
}
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...
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.
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);
}
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);
}
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 Dispose
s, then Abort
s the channel inside a ThreadPool
's thread, so an exception will not crash your AppDomain
. (Something I learnt the hard way too...)
If boolean arithmetic is not for you, then here is a simple class to manipulate flag enum
s, 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));
}
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.
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);
}
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);
source.AssertHasNoListener();
}
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);
source.AssertHasNoListener();
}
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.
Hope you'll like it, but I'm curious about you. What are your best personal utility classes ?