Archive for the ‘.NET’ tag
OCInject Release 2
When I originally released OCInject I omitted one important feature, lifestyle management. This coupled with the release of a feature full TinyIOC has made me re-evaluate my position on not adding too many features to OCInject. Release 2 of OCinject brings the following features:
- Life style management – It’s possible to register types as singletons or instance
- Func<T> factories – OCInject from day one supported delegate factories, now you can use Func<TContract> instead of typed delegates
- Simplified Registrations – In the previous release of OCInject types are registered using TContract –> TImplemenation to enforce programming to interface. It’s now possible to register with TContract as the concrete type with one call
- Largest Resolvable Constructor – In the previous release of OCInject it simply grabbed the first constructor it found. It will now select the greediest constructor it can resolve. It makes the assumption that any known types are resolvable, for performance reasons.
- Unresolveable Callback – It is now possible to supply a call back function if the container can’t resolve a type.
- Child Container Support – OCInject can create child containers that call back to the parent for any unknown types.
The latest stable version can be downloaded from Codeplex and all stableish development releases can be found at BitBucket.
Future Features
One major feature still missing from OCInject is named registrations. This is because I personally dislike ‘magic strings’, with this in mind a planned future feature of OCInject is factory delegate registration only. Also, auto generated factories from interfaces. More to come on this in a future post.
Life Style Management
By default all types registered with the OCInject container are transient. You can register a type as singleton in two ways. The first method is to use .AsSingleton() this will cause the object to be created the first time it is requested. The second method is to use .AlwaysReturnObject(obj), this will return the instance you specified. When using either method, if the type implements IDisposable it will be disposed when the container is. Usage example:
ClassFactory container = new ClassFactory();
//Normal Singleton
container.RegisterType<TestClass>()
.AsSingleton();
//Preconstructed Singleton
AnotherClass instanceOfAClass = new AnotherClass();
container.RegisterType<TestClass>()
.AlwaysReturnObject(instanceOfAClass);
Func<T> Factories
When resolving constructors if OCInject discovers a Func<T> where T is a registered type, it will pass in a func to create the type. This uses the standard container resolve, so if T is a singleton you will always get the same instance when the factory is called. Usage example:
class FuncConsumer
{
public FuncConsumer(Func<TestClass> factory)
{
}
}
ClassFactory container = new ClassFactory();
container.RegisterType<FuncConsumer>();
container.RegisterType<TestClass>();
//Successfully created with the ability to create TestClass
FuncConsumer f = container.ManufactureType<FuncConsumer>();
Simplified Registrations
Registrations no longer require the separation of contract and implement so just an implementation can be registered. Usage example:
ClassFactory container = new ClassFactory(); container.RegisterType<TestClass>(); var t = container.ManufactureType<TestClass>();
Largest Resolvable Constructor
This is quite a complicated area that is worthy of a blog post itself but OCInject’s behaviour has changed. When creating a type the constructors are ordered so the largest, in terms of parameters, is first. It then looks at each parameter and to see if it can resolve it, first by checking ‘resolve time args’ (values passed in when the resolve is requested, normally from generated factories) then by seeing if the type is a registered contract within the container. It does not check if the type can be created just that it knows about it, if it’s registered it assumes it can be created.
The first completely resolvable constructor will be used to construct the type.
Unresolveable Callback
If the container is unable to resolve the type you can now register a function that is called before the container throws an exception. To do this you need register a Func<Object, Type> with the CallToResolve propriety. Returning null will cause the container to throw an exception. Usage example:
ClassFactory container = new ClassFactory();
container.CallToResolve = (type) => { return new TestClass(); };
ITestClass manufacturedType = factory.ManufactureType<ITestClass>();
Child Container Support
Calling CreateChildContainer() will return a new ClassFactory object with no registrations but a link back to the parent. If a type is not known to the child it will ask the parent to fulfil the request. Any registrations with the child will not effect the parent and singletons registered with the child will be disposed when it is. Usage example:
ClassFactory container = new ClassFactory(); ClassFactory child = factory.CreateChildContainer();
Passing Reference Types Using Ref, Take Two
In my last post I talked about passing reference types using the ref keyword but it didn’t make a lot of sense. So I just want to go over it again, hopefully making a bit more sense.
When a method is called in C# a copy of the all parameters are given to the method. This is fairly obvious with value types because if we change the value of an int, for example, the caller does not get the updated value.
However this is not so clear for reference types. The called method can update the state of the object it was passed, for example append extra data to a StringBuilder, and the caller’s object will have these updates. This can lead to confusion about what is really happening, it looks as if the StringBuilder was passed by reference but a copy of the reference to it was taken.
It maybe subtle semantics under normal use but it becomes key to understanding behaviour when the ref keyword is used. For value types this means that if we increment an int we are passed, the caller will have the new value too. For reference types the reference we are passed is actually a reference to the caller’s reference. Meaning if we assign a new reference to it, the caller will get the new reference.
We can demonstrate this with the following code:
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Added by Main");
AddToSBPassedAsNormal(sb);
Console.Write(sb.ToString());
//Output: Added by Main
// AddToSBPassedAsNormal
AddToSBPassedByRef(ref sb);
Console.Write(sb.ToString());
//Output: AddToSBPassedByRef
AddToSBPassedAsNormalNewUsed(sb);
Console.Write(sb.ToString());
//Output: AddToSBPassedByRef
Console.ReadLine();
}
private static void AddToSBPassedAsNormal(StringBuilder sb)
{
sb.AppendLine("AddToSBPassedAsNormal");
}
private static void AddToSBPassedByRef(ref StringBuilder sb)
{
sb = new StringBuilder();
sb.AppendLine("AddToSBPassedByRef");
}
private static void AddToSBPassedAsNormalNewUsed(StringBuilder sb)
{
sb = new StringBuilder();
sb.AppendLine("AddToSBPassedAsNormalNewUsed");
}
From the code above we can see that the StringBuilder after the first method contains both strings. But after the method call, where it is passed by ref, the previously entered data has been lost and, finally, using new when not being passing by reference has no effect on Main()’s reference to the StringBuilder.
Before passing a reference type using the ref keyword you must think carefully about the implications of the caller changing the reference. As it can lead to some esoteric and difficult to track down bugs.
Introducing OCInject
**Update** I’ve created a CodePlex project: http://ocinject.codeplex.com
I’ve been learning about Dependency Injection (DI) and Inversion of Control, one of the ways I’ve done this is by creating my own mini DI framework for use in DirLinker. I’ve, also, looked at the big name frameworks and read lots along the way but I want to give something back to the community that has taught me so much. So I’m releasing my tiny DI framework used in DirLinker independently as OCInject.
OK, So Why Is This Different To X
My aim when creating OCInject was to create something that can be used in small projects, single exe utilities or one off apps, where you want the advantages of a DI container but without the overhead of Castle, Autofac, et al. So consider this DI lite, you simply take the two files, IClassFactory.cs and ClassFactory.cs, and drop them in to your project. That’s it, done, no external dependency and no XML config file. What do you get?
Features:
- A DI Container with fluent like configuration
- Ability to resolve constructor parameters for registered types and passed in constructor arguments
- Runtime delegate factory generation
- Pseudo session support via IDisposable.
The feature list is tiny and is very unlikely to grow; well maybe by one, singleton support. It is not meant to compete with or to replace anything that already exists.
How To Use It
Basic Resolution
As I said above first thing to do is copy IClassFactory.cs and ClassFactory.cs into your project, then fill the container and resolve your type. For example
public interface IMyClass
{ }
public class MyClass : IMyClass
{ }
public class MyApp
{
public void Run()
{
IClassFactory factory = new ClassFactory();
factory.RegisterType<IMyClass, MyClass>();
IMyClass myClass = factory.ManufactureType<IMyClass>();
}
}
If the class has dependencies we can inject these just by specifying them as constructor arguments on our class and the container will resolve them if they are registered. For example
public interface IMyClassWithDepend
{}
public class MyClassWithDepend
{
public MyClassWithDepend(IMyClass depend)
{ }
}
public class MyApp
{
public void Run()
{
IClassFactory factory = new ClassFactory();
factory.RegisterType<IMyClassWithDepend, MyClassWithDepend>();
factory.RegisterType<IMyClass, MyClass>();
IMyClassWithDepend myClass = factory.ManufactureType<IMyClassWithDepend>();
}
}
Auto Delegate Factories
For auto generated delegate factories we need to create a delegate that returns the contract type. Then register this with the container using the WithFactory<T> method when registering the type. For example:
public delegate IMyClassCreatedByFactory FactoryMethodName();
public interface IMyClassCreatedByFactory
{ }
public class MyClassCreatedByFactory
{ }
public class FactoryConsumer : IFactoryConsumer
{
FactoryMethodName _Factory;
public FactoryConsumer(FactoryMethodName factory)
{ _Factory = factory; }
public void DoWork()
{
IMyClassCreatedByFactory c = _Factory();
}
}
public class MyApp
{
public void Run()
{
IClassFactory factory = new ClassFactory();
factory.RegisterType<IFactoryConsumer, FactoryConsumer>();
factory.RegisterType<IMyClassCreatedByFactory, MyClassCreatedByFactory>()
.WithFactory<FactoryMethodName>();
IFactoryConsumer myClass = factory.ManufactureType<IFactoryConsumer>();
myClass.DoWork();
}
}
Auto Delegate Factories With Parameters
Delegate factories can take parameters and pass them on to the constructors of objects. This is still a bit limited because it doesn’t intelligently select the correct constructor, just the first it comes across (maybe a feature for the future
). To use them just add parameters to your delegate declaration and a create a constructor on your implementation type that matches. You can still have dependencies that are resolved by the container in the constructor, for example:
public delegate IMyClassCreatedByFactory FactoryMethodName(String param1);
public interface IMyClassCreatedByFactory
{ }
public class MyClassCreatedByFactory
{
public MyClassCreatedByFactory(IMyClass myClass, String param)
{ }
}
public class FactoryConsumer : IFactoryConsumer
{
FactoryMethodName _Factory;
public FactoryConsumer(FactoryMethodName factory)
{ _Factory = factory; }
public void DoWork()
{
IMyClassCreatedByFactory c = _Factory("OCInject filling a gap that doesn't exist");
}
}
public class MyApp
{
public void Run()
{
IClassFactory factory = new ClassFactory();
factory.RegisterType<IMyClass, MyClass>();
factory.RegisterType<IFactoryConsumer, FactoryConsumer>();
factory.RegisterType<IMyClassCreatedByFactory, MyClassCreatedByFactory>()
.WithFactory<FactoryMethodName>();
IFactoryConsumer myClass = factory.ManufactureType<IFactoryConsumer>();
myClass.DoWork();
}
}
Where to Get it From and Further Examples
You can download it from BitBucket at http://bitbucket.org/humblecoder/ocinject/. I don’t have any documentation at the moment but you can look at the DirLinker source and the unit tests for OCInject for more examples.
Enjoy and I hope someone finds it useful
I Was Wrong About Delegate Factories “Micro Optimisations”
In my previous post I talked about creating typed delegate factories, towards the end of the post I talked about optimising the performance by avoiding boxing when passing value type parameters around. My premise was that if we could use generics to select strongly typed method signatures for the method that constructs the type we could avoid the boxing and unboxing of value types. I think outside of dependencies, the most common constructor arguments is going to be value types. But I was wrong.
Why?
It all boils down to Constructor.Invoke, this is the method my tiny dependency injection framework uses to create new instances of objects from the container. Its only signature takes params object[] so all our hard work is useless because the values will be boxed for this call.
The biggest thing I was wrong about, though, was that reflection is quicker than boxing. Lets look at the timing of the reflective generic approach:
So generating the factory takes 79ms when you reflect over the type and remove any generics. But what about calling using params object[].
This takes 31ms to create the factory. So it is quite clear that, at least upfront, using the param approach is substantially quicker. One thing I will point out is, the tests didn’t use the factories to create any types. But the values will still be boxed when passed to the invoke method so I would still expect the second method to be more performant.
My point is that we need to look more closely at how we are going to use the code and if there is any optimisation, like caching the generated delegates, that would speed up calls after taking an initial hit. If we didn’t need to make the call Constructor.Invoke would the second approach still be quicker overall in our application?
Creating Typed Delegates at Runtime Using Expression Trees
In my previous post I talked about using the abstract factories pattern instead of the service locator pattern. Towards the end of the post I went on to talk about delegate factories and I want to clear up any misunderstanding before going any further. I think injecting the factory via the constructor is the right way to do this, the delegate factories I talked about are just a simplification and a way to remove the need to write a lot of simple and repetitive code. I don’t think it helps that I switched example code towards the end. So here is an example using IFile / FileConsumer.
delegate IFile IFileFactoryForFileName(String fileName);
public class FileConsumer
{
private IFileFactoryForFileName CreateFileForFileName;
public FileConsumer(IFileFactoryForFileName ifileFactory)
{
CreateFileFromFileName = ifileFactory;
}
public void DoSomething()
{
IFile fileA = CreateFileForFileName("test.txt");
//uses fileA
}
}
In this example we don’t have an interface and implementation for a factory just the delegate declaration, this would live near the IFile interface, and we will trust the container to wire this up for us when it is resolving the constructor arguments. This leads nicely into the how.
All About Expression
When first looking at the problem of how to generate the delegates I thought easy, anonymous delegates or lambdas and let type inference take care of the rest but the reality is somewhat more complicated. The best way to achieve this is using Expression Trees.
Expression trees are the foundation of LINQ and a high level abstraction that allow you to treat a tree of objects as code. This allows us to build an expression at runtime that represents the required factory then compile it to a lambda and finally the delegate we require.
All this starts at the Expression class, it is an abstract class that is used as a base class for Expression objects that represent the various things we can do. It, also, has static methods that create the relevant expression objects for us. The ones we are interested in are:
- ParameterExpression – This is what it sounds like, it allows us to create a parameter that is going to be passed into and used in by the expression.
- ConstantExpression – Again it’s obvious what this does, it represents a value that will not change for the life time of the expression.
- NewArrayExpression – This represents the creation of an array and its content within the expression.
- MethodCallExpression – This allows the expression to call external methods, so far I’ve only been able to get this to work for public statics but this is not a major problem
- Finally, LambdaExpression – This allows us to pull all of elements together and compile it into a lambda or, as in this case, a delegate of the type supplied, so long as the return type and parameters match.
Now we know what we are going to be use, lets look at how we generate the factory:
public virtual void RegisterDelegateFactoryForType<TResult, TFactoryDelegateType>()
{
MethodInfo delegateInvoker = typeof(TFactoryDelegateType).GetMethod("Invoke");
ParameterExpression[] factoryParams = GetParamsAsExpressions(delegateInvoker);
//Build the factory from the template
MethodInfo mi = typeof(ClassFactory).GetMethod("FactoryTemplate");
mi = mi.MakeGenericMethod(typeof(TResult));
Expression call = Expression.Call(mi, new Expression[] {Expression.Constant(this),
Expression.NewArrayInit(typeof(Object), factoryParams)} );
TFactoryDelegateType factory = Expression.Lambda<TFactoryDelegateType>(call, factoryParams).Compile();
_typeFactories.Add(typeof(TFactoryDelegateType), factory as Delegate);
}
private ParameterExpression[] GetParamsAsExpressions(MethodInfo mi)
{
List<ParameterExpression> paramsAsExpression = new List<ParameterExpression>();
Array.ForEach<ParameterInfo>(mi.GetParameters(),
p => paramsAsExpression.Add(Expression.Parameter(p.ParameterType, p.Name)));
return paramsAsExpression.ToArray();
}
public static T FactoryTemplate<T>(ClassFactory factory, params Object[] args)
{
return factory.ManufactureType<T>(args);
}
Starting at the top we use the MethodInfo for the Invoke method of the delegate to get the all the parameters for the required delegate. We then get a MethodInfo for a template method that uses generics, it is important at this point we replace the generic parameters with the concrete types otherwise the compiling of the lambda expression to the delegate will fail. It then sets up the call to the template factory method, builds the correctly typed delegate and adds it to a collection of prebuilt delegates ready to be passed into constructors. This expression tree basically builds a lambda expression that looks like the following:
delegate myInterface myInterfaceFactory(String a, String b) //transform to (String a, String b) => FactoryTemplate(classfactory, a, b);
Memory and Performance Considerations
Before wrapping up, lets just reflect over the performance and memory implications of this. We are using delegates and statics, a typical recipe for disaster in the managed world but fear not. The use of the constant expression that relates to the ClassFactory effectively adds a new root to the ClassFactory instance but the class factory object holds the roots to the delegates. This means before the ClassFactory instance goes out of scope we need to dispose it correctly to ensure we release the roots to the delegates. In reality, this is unlikely to cause us problems as we would normally want the ClassFactory instance to last as long as the application.
What might be a performance problem though is the potential boxing and unboxing of value types that is caused by passing parameters into the FactoryTemplate method as an Object array. There is no easy answer to this because when we don’t know up front how many parameters we are going to need or what type. We could, however, make a micro optimisation to avoid it by offering several overloads that take between 0 and 4 parameters before falling back on to a params function with the idea that most people won’t need that many. I will leave the exercise of converting the expression tree to use the correct generic template factory to the reader
Although I haven’t committed the latest changes, I do have this 90% done and I will push to CodePlex soon. I am going to pull out he DI stuff I’ve been working on and host it at BitBucket.
Detangling Service Locator From Dependency Injection
I’m sure like many exploring Dependency Injection (DI) for the first time the biggest problem I had, was how to rid the world of those pesky little new statements. The first application I tried to use DI with in anger was DirLinker. I had no prior knowledge of any of the DI frameworks and started looking at patterns that would help me remove all the new statements. Unfortunately, I hit up on service locator and the rest is a mess history. I ended up with code the looks like the following inside DirLinker:
IFile aFile = ClassFactory.CreateInstance<IFile>(); aFile.SetFile(file);
There is a couple of things that bother me about this. First is the static, I’m not a fan of statics at all, infact, I hate them. Next is the SetFile call, for any meaningful work to be done with this class you need to pass in a filename and it should be a constructor argument. In all fairness the SetFile problem is more to do with the limitations of my roll your own DI framework than anything else.
In spite of my niggling doubts, it worked so I left it alone. Fast forward to last week when I came across a blog post entitled Service Locator is an Anti-Pattern. This confirmed my initial discomfort and highlighted a problem I hadn’t thought of, namely that the class doesn’t advertise its dependencies. Very bad for reuse.
Factories
As the blog post suggests a better way of doing this would have been to use factories so lets go over a couple of examples on how this could be achieved.
Virtual Instance Methods
This is a method I would use when trying to a create a seam in legacy code to inject a dependency for unit testing. To do this you create a virtual method on the class that needs to create the object. In the unit test inherit from the class under test and override the factory method to return your mock or stub. For example:
public class FileConsumer
{
protected virtual IFile GetFile(String filename)
{
return new FileImp(filename);
}
public void DoSomething()
{
IFile fileA = GetFile("test.txt");
IFile fileB = GetFile("test2.txt");
//uses files
}
}
[TestFixture]
public class FileConsumerTests : FileConsumer
{
protected override IFile GetFile(string filename)
{
return new FileMock(filename);
}
[Test]
public void DosomethingTest()
{
//Code to perform test
}
}
This is good because it’s clear to any maintainer what the dependency is and where it is coming from.
Abstraction Factory Pattern
This would loudly and proudly advertise the dependency on the ability to create IFile objects. It works by creating a class with methods solely responsible for creating IFile objects and then taking this as dependency for your class. For example:
public interface IFileFactory
{
IFile CreateFile(String filename);
}
public class FileFactory : IFileFactory
{
public IFile CreateFile(string filename)
{
return new FileImp(filename);
}
}
public class FileConsumer
{
IFileFactory _fileFactory;
public FileConsumer(IFileFactory fileFactory)
{
_fileFactory = fileFactory;
}
public void DoSomething()
{
IFile fileA = _fileFactory.CreateFile("test.txt");
IFile fileB = _fileFactory.CreateFile("test.txt");
//uses files
}
}
This is the pattern recommended by the blog post and it covers all the things I don’t like about Service Locator. But I think we could take advantage of some of C#’s language features and the fact we are creating objects via a container to achieve something similar but with less code.
Delegate Factories
Before I go into this a little disclaimer, this is totally and utterly inspired by Autofac’s wonderful generated delegate factory functionality, you can read more about it here.
OK, honesty out of way lets look at what the container knows and what it does. The DI container knows what Interfaces should map on to what concrete types and it has the ability to resolve constructor arguments for types that it knows about. This is just a generic version of a factory so it makes sense to take advantage of it.
One way would be to use Func<TResult>() (and its friends). If the class being constructed requires a constructor parameter of Func<TResult> where TResult is the required interface, the container could generate an appropriate delegate at runtime and pass it in. For example:
public class FileConsumer
{
Func<IFile> _fileFactory;
public FileConsumer(Func<IFile> fileFactory)
{
_fileFactory = fileFactory;
}
public void DoSomething()
{
IFile fileA = _fileFactory();
IFile fileB = _fileFactory();
//uses fileA
}
}
This would require a slight modification to the container and could be extended by the use of Func<T, Tn, TResult>(T value, Tn valuen). The container would match the parameters to a suitable constructor.
This is quite a powerful and time saving concept but I don’t like the vagueness of Func<TResult>(), it’s not as expressive as it could be. So the method I have chosen for DirLinker is to use strongly typed delegates and generate them at runtime from the container. It works in the same manner only you declare the delegate up front and pass them in as an argument. This, also, requires a bit of configuration but the pay off is worth it. I have started work on the implementation for DirLinker so this example is taken directly from the unit tests and can be found here.
interface ITestClassWithDelegateFactory { ITestClassFactory Factory { get; set; } }
delegate ITestClass ITestClassFactory();
class TestClassWithDelegateFactory : ITestClassWithDelegateFactory
{
public ITestClassFactory Factory { get; set; }
public TestClassWithDelegateFactory(ITestClassFactory delegateFactory)
{
Factory = delegateFactory;
}
}
[Test]
public void ManufactureType_Type_delegate_factory_manufactures_correct_type()
{
IClassFactory testClassFactory = new ClassFactory();
testClassFactory.RegisterType<ITestClass, TestClass>()
.WithFactory<ITestClassFactory>();
testClassFactory.RegisterType<ITestClassWithDelegateFactory, TestClassWithDelegateFactory>();
ITestClassWithDelegateFactory manufacturedType =
testClassFactory.ManufactureType<ITestClassWithDelegateFactory>();
ITestClass instance = manufacturedType.Factory();
Assert.IsInstanceOf(typeof(TestClass), instance);
}
Admittedly there is quite a lot going on here but the main points are we registered a type and factory in a strongly typed manner with the container. Then pull it out and use it to create an instance of a different type. I am going to cover this in quite some detail along with the how to create strongly typed delegates at runtime in my next post.
Don’t Be a Fool, Wrap Your Tool!
As a hormone ravaged teenage, I squirmed uncomfortably as parents, teachers and community health practitioners imparted the words of wisdom “Don’t be a fool, wrap your tool”. So it is fitting, I’m equally as squeamish when coming across the same advice as an adult.
What am I talking about? Creating wrappers for anything at all on the boundaries of your code for the purpose of unit testing. I’ve been struggling to think of a succinct way to explain this so I decided to go through a worked example.
Consider the following code:
public class CommandReceiver
{
public void WaitForMessage()
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.In))
{
// Wait for a client to connect
Trace.Write("Waiting for client connection...");
pipeServer.WaitForConnection();
Trace.WriteLine("Client connected.");
try
{
// Read user input and send that to the client process.
using (StreamReader sr = new StreamReader(pipeServer))
{
String command = sr.ReadLine();
DispatchCommand(command);
}
}
catch (IOException e)
{
Trace.WriteLine("ERROR: {0}", e.Message);
}
}
}
private void DispatchCommand(String command)
{
//Knows how to deal with messages.
}
}
Looking at this code there is a number of problems but lets focus on the unit testing problems. It is impossible to unit test this code because it creates a real pipe server and waits on a blocking call before continuing. This means to test this code we need to create a pipe client, connect and all this would have to be threaded because of the blocking call. Of course, this would make a good integration test because it tests that the pipe is connectable and receives a string message.
Before we set about making this code more unit test friendly, lets look at what we are trying to unit test. We are trying to test that the WaitForMessage method can receive a string and pass it on. For us to do this we need to abstract the pipe and stream out. Also, while we are there lets remove the DispatchCommand method since it violates SRP and it would be more testable on its own. So lets take a second stab at the code.
public interface INamedPipeServer : IDisposable
{
void WaitForConnection();
}
public class ManagedNamedPipeServer : INamedPipeServer
{
private NamedPipeServerStream _pipeServer;
public ManagedNamedPipeServer(String name, PipeDirection pipeDir)
{
_pipeServer = new NamedPipeServerStream(name, pipeDir);
}
public void WaitForConnection()
{
_pipeServer.WaitForConnection();
}
public void Dispose()
{
_pipeServer.Dispose();
}
}
public interface IStreamReader: IDisposable
{
String ReadLine();
}
public class ManagedStreamReader : StreamReader, IStreamReader
{
public ManagedStreamReader(Stream stream) : base(stream)
{}
}
public class CommandReceiver : ICommandReceiver
{
INamedPipeServer _NamedPipeServer;
ICommandDispatcher _CommandDispatcher;
public CommandReceiver(INamedPipeServer pipeServer, ICommandDispatcher dispatch)
{
_NamedPipeServer = pipeServer;
_CommandDispatcher = dispatch;
}
protected virtual IStreamReader GetStreamReader()
{
//Code to create a stream reader from the pipe
}
public void WaitForMessage()
{
// Wait for a client to connect
Trace.Write("Waiting for client connection...");
_NamedPipeServer.WaitForConnection();
Trace.WriteLine("Client connected.");
try
{
// Read user input and send that to the client process.
using (var sr = GetStreamReader())
{
String command = sr.ReadLine();
_CommandDispatcher.DispatchCommand(command);
}
}
catch (IOException e)
{
Trace.WriteLine("ERROR: {0}", e.Message);
}
}
}
This is where my uncomfortable squirm returns because my “keep-it-simple” sense is tingling. I’ve just taken a fairly simple class that was around 30 lines and turned it into 75 lines of complicated OOP code. I would hope that anyone reading this can follow it but in a real project this will probably be split over several files and the two styles of wrapping (because NamedPipeServerStream is sealed) can add significant cognitive burden to understanding what is going on.
What benefits does this bring? It allows us to unit test that we read a string and pass it on to a dispatcher. But I would go out on a limb and say that this is least likely of all the code in that class to go wrong. The real problem area will be in connecting the pipe and reading from it. We can make assumptions about failure conditions from the docs but as we all know docs != reality.
Is the abstraction here a benefit? In my opinion, not to the extreme level we have. The abstraction at ICommandReceiver will allow us to swap out how the application does IPC calls making it flexible in the future and, as I eluded to above, the unit test ‘coverageability’ is of lower value in this instance.
My point in all this rambling nonsense? In an ideal world we would have both sets of tests and the unit tests would cover all the error conditions but in the real world we only have a finite and, usually, short amount of time with pressure from project managers and deadlines. So we have to look at what will bring us the most value and focus on that. I believe at application boundaries like this one we should focus our attention on writing integration tests because it will bring us more value in the long run. I would not shun unit testing entirely and in this example the ICommandDisptacher and other supporting classes would have a full suite of unit tests.
As a side note, my final version of the code would be a mid way point between the two listings.