This week I have spent an inordinate amount of time doing more C# generics coding than I have before in my life. And there have been very few things in the recent past that has made me feel that I'd rather be coding proper C++, if I couldn't be using Python or Ruby (which would make the task almost trivial).
The problem -- make a set of interfaces to wrap part of the
System.DirectoryServices.ActiveDirectory namespaces, so as to make them mockable.
What seemed an easy job of mocking about half a dozen classes and a few methods on each has turned into a major exercise, because they all return different trivial collection classes (like this one) which don't present any public constructors.
Writing a basic
Wrapper<T> to hold a
T provided at construction time, subclassing it to do delegation for standard interfaces like
IDisposable -- or even
ICollection -- no problem, defining interfaces for the parts of the concrete types and writing specific
Wrapper subclasses, easy.
The problem comes when wrapping a collection of type
T, which contains entities of type
U, which have to be exposed as wrapper sub-type
Wrapper<U>). Not only do I have to suppress FxCop nagging about 3-way generics, but when I write the
this[string index] or the
Current property of a custom
Wrapper<IEnumerator>, I would like to write
return new V(Wrapped[index]);or in expanded form with the types made explicit
U internal = Wrapped[index]; //delegate to wrapped object return new V(internal);
but I can't, because I'm only allowed to get at a public default constructor for
V -- unlike the duck-typing in a C++ template, which would allow me to write the desired code. Which means I'm forced to violate the desired immutability and put a setter on the
Wrapped property, and allow null internal objects. At least I can put a generic wrapping function
V Wrap<U,V>(U input) in the base class which can be the only thing to use it (by making the setter private) -- and then suppress the FxCop nagging on the generic function about having generic types not implied by context.
And talking of FxCop nagging -- on more than one occasion a concrete wrapper named for the wrapped type
Win32[NameOfWrappedType], or method in the partial interface, got hauled up on violating naming conventions because the MSFT prototype name did so. *sigh* My code gets more and more impure, all the while as I'm simply writing code and unit tests for that code, which I wouldn't need to have written at all if it weren't for unit testing the code I really want to write.