diff options
Diffstat (limited to 'src/Notepad/Infrastructure')
23 files changed, 503 insertions, 0 deletions
diff --git a/src/Notepad/Infrastructure/Container/DependencyResolutionException.cs b/src/Notepad/Infrastructure/Container/DependencyResolutionException.cs new file mode 100644 index 0000000..fe36112 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/DependencyResolutionException.cs @@ -0,0 +1,9 @@ +using System;
+using Notepad.Infrastructure.Extensions;
+
+namespace Notepad.Infrastructure.Container {
+ public class DependencyResolutionException<T> : Exception {
+ public DependencyResolutionException(Exception innerException)
+ : base("Could not resolve {0}".FormatWith(typeof (T).FullName), innerException) {}
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/IDependencyRegistry.cs b/src/Notepad/Infrastructure/Container/IDependencyRegistry.cs new file mode 100644 index 0000000..fbcd911 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/IDependencyRegistry.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic;
+
+namespace Notepad.Infrastructure.Container {
+ public interface IDependencyRegistry {
+ Interface FindAnImplementationOf<Interface>();
+ IEnumerable<Interface> AllImplementationsOf<Interface>();
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/Resolve.cs b/src/Notepad/Infrastructure/Container/Resolve.cs new file mode 100644 index 0000000..507ccb4 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/Resolve.cs @@ -0,0 +1,20 @@ +using System;
+
+namespace Notepad.Infrastructure.Container {
+ public static class Resolve {
+ private static IDependencyRegistry underlyingRegistry;
+
+ public static void InitializeWith(IDependencyRegistry registry) {
+ underlyingRegistry = registry;
+ }
+
+ public static DependencyToResolve DependencyFor<DependencyToResolve>() {
+ try {
+ return underlyingRegistry.FindAnImplementationOf<DependencyToResolve>();
+ }
+ catch (Exception e) {
+ throw new DependencyResolutionException<DependencyToResolve>(e);
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/ResolveSpecs.cs b/src/Notepad/Infrastructure/Container/ResolveSpecs.cs new file mode 100644 index 0000000..e16d137 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/ResolveSpecs.cs @@ -0,0 +1,83 @@ +using System;
+using MbUnit.Framework;
+using Notepad.Presentation.Core;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Infrastructure.Container {
+ public class ResolveSpecs {}
+
+ [TestFixture]
+ public class when_resolving_a_dependency_using_the_resolve_gateway_ {
+ private MockRepository mockery;
+ private IDependencyRegistry registry;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ registry = mockery.DynamicMock<IDependencyRegistry>();
+ Resolve.InitializeWith(registry);
+ }
+
+ [Test]
+ public void should_leverage_the_underlying_container_it_was_initialized_with() {
+ var presenter = mockery.DynamicMock<IPresenter>();
+
+ using (mockery.Record()) {
+ Expect
+ .Call(registry.FindAnImplementationOf<IPresenter>())
+ .Return(presenter)
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ Resolve.DependencyFor<IPresenter>();
+ }
+ }
+
+ [Test]
+ public void should_return_the_resolved_dependency() {
+ var presenter = mockery.DynamicMock<IPresenter>();
+
+ using (mockery.Record()) {
+ Expect
+ .Call(registry.FindAnImplementationOf<IPresenter>())
+ .Return(presenter)
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ Resolve.DependencyFor<IPresenter>().ShouldBeEqualTo(presenter);
+ }
+ }
+ }
+
+ [TestFixture]
+ public class when_resolving_a_dependency_that_is_not_registered_ {
+ private MockRepository mockery;
+ private IDependencyRegistry registry;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ registry = mockery.DynamicMock<IDependencyRegistry>();
+ Resolve.InitializeWith(registry);
+ }
+
+ [Test]
+ [ExpectedException(typeof (DependencyResolutionException<IPresenter>))]
+ public void should_throw_a_dependency_resolution_exception() {
+ using (mockery.Record()) {
+ SetupResult
+ .For(registry.FindAnImplementationOf<IPresenter>())
+ .Throw(new Exception());
+ }
+
+ using (mockery.Playback()) {
+ Resolve.DependencyFor<IPresenter>();
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/Windsor/IComponentExclusionSpecification.cs b/src/Notepad/Infrastructure/Container/Windsor/IComponentExclusionSpecification.cs new file mode 100644 index 0000000..b611859 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/Windsor/IComponentExclusionSpecification.cs @@ -0,0 +1,15 @@ +using System;
+using System.Windows.Forms;
+using Notepad.Infrastructure.Core;
+
+namespace Notepad.Infrastructure.Container.Windsor {
+ public interface IComponentExclusionSpecification : ISpecification<Type> {}
+
+ public class ComponentExclusionSpecification : IComponentExclusionSpecification {
+ public bool IsSatisfiedBy(Type type) {
+ return type.GetInterfaces().Length == 0
+ || type.IsSubclassOf(typeof (Form))
+ || type.IsAssignableFrom(typeof (IDependencyRegistry));
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/Windsor/IWindsorContainerFactory.cs b/src/Notepad/Infrastructure/Container/Windsor/IWindsorContainerFactory.cs new file mode 100644 index 0000000..4087a5e --- /dev/null +++ b/src/Notepad/Infrastructure/Container/Windsor/IWindsorContainerFactory.cs @@ -0,0 +1,42 @@ +using Castle.MicroKernel.Registration;
+using Castle.Windsor;
+using Notepad.Infrastructure.Extensions;
+
+namespace Notepad.Infrastructure.Container.Windsor {
+ public interface IWindsorContainerFactory {
+ IWindsorContainer Create();
+ }
+
+ public class WindsorContainerFactory : IWindsorContainerFactory {
+ private static IWindsorContainer container;
+ private IComponentExclusionSpecification criteriaToSatisfy;
+
+ public WindsorContainerFactory() : this(new ComponentExclusionSpecification()) {}
+
+ public WindsorContainerFactory(IComponentExclusionSpecification criteriaToSatisfy) {
+ this.criteriaToSatisfy = criteriaToSatisfy;
+ }
+
+ public IWindsorContainer Create() {
+ if (null == container) {
+ container = new WindsorContainer();
+ container.Register(
+ AllTypes
+ .Pick()
+ .FromAssembly(GetType().Assembly)
+ .WithService
+ .FirstInterface()
+ .Unless(criteriaToSatisfy.IsSatisfiedBy)
+ .Configure(
+ delegate(ComponentRegistration registration) {
+ this.LogInformational("{1}-{0}", registration.Implementation, registration.ServiceType.Name);
+ if (registration.Implementation.GetInterfaces().Length == 0) {
+ registration.For(registration.Implementation);
+ }
+ })
+ );
+ }
+ return container;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyRegistry.cs b/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyRegistry.cs new file mode 100644 index 0000000..75cc206 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyRegistry.cs @@ -0,0 +1,40 @@ +using System;
+using System.Collections.Generic;
+using Castle.Windsor;
+using Notepad.Infrastructure.Extensions;
+
+namespace Notepad.Infrastructure.Container.Windsor {
+ public class WindsorDependencyRegistry : IDependencyRegistry {
+ private IWindsorContainer underlyingContainer;
+
+ public WindsorDependencyRegistry() : this(new WindsorContainerFactory()) {}
+
+ public WindsorDependencyRegistry(IWindsorContainerFactory factory) {
+ underlyingContainer = factory.Create();
+ }
+
+ public Interface FindAnImplementationOf<Interface>() {
+ return underlyingContainer.Kernel.Resolve<Interface>();
+ }
+
+ public void Register(Type typeOfInterface, Type typeOfImplementation) {
+ underlyingContainer
+ .Kernel
+ .AddComponent("{0}-{1}".FormatWith(typeOfInterface.FullName, typeOfImplementation.FullName),
+ typeOfInterface,
+ typeOfImplementation);
+ }
+
+ public void Register<Interface, Implementation>() {
+ Register(typeof (Interface), typeof (Implementation));
+ }
+
+ public void RegisterInstanceOf<Interface>(Interface instanceOfTheInterface) {
+ underlyingContainer.Kernel.AddComponentInstance<Interface>(instanceOfTheInterface);
+ }
+
+ public IEnumerable<Interface> AllImplementationsOf<Interface>() {
+ return underlyingContainer.Kernel.ResolveAll<Interface>();
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyResolverSpecs.cs b/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyResolverSpecs.cs new file mode 100644 index 0000000..8235643 --- /dev/null +++ b/src/Notepad/Infrastructure/Container/Windsor/WindsorDependencyResolverSpecs.cs @@ -0,0 +1,73 @@ +using Castle.Windsor;
+using MbUnit.Framework;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Infrastructure.Container.Windsor {
+ public class WindsorDependencyResolverSpecs {}
+
+
+ [TestFixture]
+ public class when_registering_a_singleton_component_with_the_windsor_container_ {
+ private WindsorDependencyRegistry sut;
+
+ [SetUp]
+ public void SetUp() {
+ sut = CreateSUT();
+ }
+
+ [Test]
+ public void should_return_the_same_instance_each_time_its_resolved() {
+ sut
+ .FindAnImplementationOf<IBird>()
+ .ShouldBeSameInstanceAs(sut.FindAnImplementationOf<IBird>());
+ }
+
+ [Test]
+ public void should_not_return_null() {
+ sut.FindAnImplementationOf<IBird>().ShouldNotBeNull();
+ }
+
+ private WindsorDependencyRegistry CreateSUT() {
+ return new WindsorDependencyRegistry();
+ }
+ }
+
+ [TestFixture]
+ public class when_creating_the_windsor_resolver_ {
+ private MockRepository mockery;
+ private IWindsorContainerFactory factory;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ factory = mockery.DynamicMock<IWindsorContainerFactory>();
+ }
+
+ [Test]
+ public void should_leverage_the_factory_to_create_the_underlying_container() {
+ var container = new WindsorContainer();
+ using (mockery.Record()) {
+ Expect
+ .Call(factory.Create())
+ .Return(container)
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT();
+ }
+ }
+
+ private IDependencyRegistry CreateSUT() {
+ return new WindsorDependencyRegistry(factory);
+ }
+ }
+
+ public class BlueBird : IBird {
+ public void Initialize() {}
+ }
+
+ public interface IBird {}
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Core/ICommand.cs b/src/Notepad/Infrastructure/Core/ICommand.cs new file mode 100644 index 0000000..1fadec3 --- /dev/null +++ b/src/Notepad/Infrastructure/Core/ICommand.cs @@ -0,0 +1,5 @@ +namespace Notepad.Infrastructure.Core {
+ public interface ICommand {
+ void Execute();
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Core/IMapper.cs b/src/Notepad/Infrastructure/Core/IMapper.cs new file mode 100644 index 0000000..39bad69 --- /dev/null +++ b/src/Notepad/Infrastructure/Core/IMapper.cs @@ -0,0 +1,5 @@ +namespace Notepad.Infrastructure.Core {
+ public interface IMapper<Input, Output> {
+ Output MapFrom(Input item);
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Core/ISpecification.cs b/src/Notepad/Infrastructure/Core/ISpecification.cs new file mode 100644 index 0000000..c61d8b9 --- /dev/null +++ b/src/Notepad/Infrastructure/Core/ISpecification.cs @@ -0,0 +1,5 @@ +namespace Notepad.Infrastructure.Core {
+ public interface ISpecification<T> {
+ bool IsSatisfiedBy(T item);
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Extensions/ConversionExtensions.cs b/src/Notepad/Infrastructure/Extensions/ConversionExtensions.cs new file mode 100644 index 0000000..0266e58 --- /dev/null +++ b/src/Notepad/Infrastructure/Extensions/ConversionExtensions.cs @@ -0,0 +1,7 @@ +namespace Notepad.Infrastructure.Extensions {
+ public static class ConversionExtensions {
+ public static T DowncastTo<T>(this object objectToCast) {
+ return (T) objectToCast;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Extensions/EnumerableExtensions.cs b/src/Notepad/Infrastructure/Extensions/EnumerableExtensions.cs new file mode 100644 index 0000000..d57c0e1 --- /dev/null +++ b/src/Notepad/Infrastructure/Extensions/EnumerableExtensions.cs @@ -0,0 +1,24 @@ +using System;
+using System.Collections.Generic;
+
+namespace Notepad.Infrastructure.Extensions {
+ public static class EnumerableExtensions {
+ public static void Walk<T>(this IEnumerable<T> itemsToWalk) {
+ foreach (var item in itemsToWalk) {}
+ }
+
+ public static IEnumerable<T> ThatSatisfy<T>(this IEnumerable<T> itemsToPeekInto, Predicate<T> criteriaToSatisfy) {
+ foreach (var item in itemsToPeekInto) {
+ if (item.Satisfies(criteriaToSatisfy)) {
+ yield return item;
+ }
+ }
+ }
+
+ public static IEnumerable<T> SortedUsing<T>(this IEnumerable<T> itemsToSort, IComparer<T> sortingAlgorithm) {
+ var sortedItems = new List<T>(itemsToSort);
+ sortedItems.Sort(sortingAlgorithm);
+ return sortedItems;
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Extensions/LoggingExtensions.cs b/src/Notepad/Infrastructure/Extensions/LoggingExtensions.cs new file mode 100644 index 0000000..a05e2fc --- /dev/null +++ b/src/Notepad/Infrastructure/Extensions/LoggingExtensions.cs @@ -0,0 +1,17 @@ +using System;
+using Notepad.Infrastructure.Logging;
+
+namespace Notepad.Infrastructure.Extensions {
+ public static class LoggingExtensions {
+ public static void LogError(this Exception errorToLog) {
+ Log.For(errorToLog).Error(errorToLog);
+ }
+
+ public static void LogInformational<T>(
+ this T typeToCreateLoggerFor,
+ string formattedMessage,
+ params object[] arguments) {
+ Log.For(typeToCreateLoggerFor).Informational(formattedMessage, arguments);
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Extensions/SpecificationExtensions.cs b/src/Notepad/Infrastructure/Extensions/SpecificationExtensions.cs new file mode 100644 index 0000000..c7ed7dc --- /dev/null +++ b/src/Notepad/Infrastructure/Extensions/SpecificationExtensions.cs @@ -0,0 +1,14 @@ +using System;
+using Notepad.Infrastructure.Core;
+
+namespace Notepad.Infrastructure.Extensions {
+ public static class SpecificationExtensions {
+ public static bool Satisfies<T>(this T itemToValidate, Predicate<T> criteriaToSatisfy) {
+ return criteriaToSatisfy(itemToValidate);
+ }
+
+ public static bool Satisfies<T>(this T itemToValidate, ISpecification<T> criteriaToSatisfy) {
+ return itemToValidate.Satisfies(criteriaToSatisfy.IsSatisfiedBy);
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Extensions/StringExtensions.cs b/src/Notepad/Infrastructure/Extensions/StringExtensions.cs new file mode 100644 index 0000000..9c19f97 --- /dev/null +++ b/src/Notepad/Infrastructure/Extensions/StringExtensions.cs @@ -0,0 +1,13 @@ +using Notepad.Domain.FileSystem;
+
+namespace Notepad.Infrastructure.Extensions {
+ public static class StringExtensions {
+ public static string FormatWith(this string formattedString, params object[] arguments) {
+ return string.Format(formattedString, arguments);
+ }
+
+ public static IFilePath AsAnAbsoluteFilePath(this string rawFilePath) {
+ return new AbsoluteFilePath(rawFilePath);
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/ILogFactory.cs b/src/Notepad/Infrastructure/Logging/ILogFactory.cs new file mode 100644 index 0000000..ce1d2e1 --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/ILogFactory.cs @@ -0,0 +1,7 @@ +using System;
+
+namespace Notepad.Infrastructure.Logging {
+ public interface ILogFactory {
+ ILogger CreateFor(Type typeToCreateLoggerFor);
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/ILogger.cs b/src/Notepad/Infrastructure/Logging/ILogger.cs new file mode 100644 index 0000000..ac7dd6f --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/ILogger.cs @@ -0,0 +1,8 @@ +using System;
+
+namespace Notepad.Infrastructure.Logging {
+ public interface ILogger {
+ void Informational(string formattedString, params object[] arguments);
+ void Error(Exception e);
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/Log.cs b/src/Notepad/Infrastructure/Logging/Log.cs new file mode 100644 index 0000000..e8a3b4c --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/Log.cs @@ -0,0 +1,15 @@ +using Notepad.Infrastructure.Container;
+using Notepad.Infrastructure.Logging.Log4NetLogging;
+
+namespace Notepad.Infrastructure.Logging {
+ public static class Log {
+ public static ILogger For<T>(T typeToCreateLoggerFor) {
+ try {
+ return Resolve.DependencyFor<ILogFactory>().CreateFor(typeof (T));
+ }
+ catch {
+ return new Log4NetLogFactory().CreateFor(typeof (T));
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogFactory.cs b/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogFactory.cs new file mode 100644 index 0000000..0784a13 --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogFactory.cs @@ -0,0 +1,20 @@ +using System;
+using System.IO;
+using log4net;
+using log4net.Config;
+
+namespace Notepad.Infrastructure.Logging.Log4NetLogging {
+ public class Log4NetLogFactory : ILogFactory {
+ public Log4NetLogFactory() {
+ XmlConfigurator.Configure(PathToConfigFile());
+ }
+
+ public ILogger CreateFor(Type typeToCreateLoggerFor) {
+ return new Log4NetLogger(LogManager.GetLogger(typeToCreateLoggerFor));
+ }
+
+ private FileInfo PathToConfigFile() {
+ return new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config.xml"));
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogger.cs b/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogger.cs new file mode 100644 index 0000000..5111622 --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/Log4NetLogging/Log4NetLogger.cs @@ -0,0 +1,20 @@ +using System;
+using log4net;
+
+namespace Notepad.Infrastructure.Logging.Log4NetLogging {
+ public class Log4NetLogger : ILogger {
+ private readonly ILog log;
+
+ public Log4NetLogger(ILog log) {
+ this.log = log;
+ }
+
+ public void Informational(string formattedString, params object[] arguments) {
+ log.InfoFormat(formattedString, arguments);
+ }
+
+ public void Error(Exception e) {
+ log.Error(e.ToString());
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/Logging/LogSpecs.cs b/src/Notepad/Infrastructure/Logging/LogSpecs.cs new file mode 100644 index 0000000..3e6aead --- /dev/null +++ b/src/Notepad/Infrastructure/Logging/LogSpecs.cs @@ -0,0 +1,40 @@ +using MbUnit.Framework;
+using Notepad.Infrastructure.Container;
+using Rhino.Mocks;
+
+namespace Notepad.Infrastructure.Logging {
+ public class LogSpecs {}
+
+ [TestFixture]
+ public class when_creating_a_logger_for_a_particular_type_ {
+ private MockRepository mockery;
+ private ILogFactory factory;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ factory = mockery.DynamicMock<ILogFactory>();
+
+ var resolver = mockery.DynamicMock<IDependencyRegistry>();
+ SetupResult.For(resolver.FindAnImplementationOf<ILogFactory>()).Return(factory);
+
+ Resolve.InitializeWith(resolver);
+ }
+
+ [Test]
+ public void should_leverage_the_log_factory_to_create_a_logger_for_the_given_type() {
+ var logger = mockery.DynamicMock<ILogger>();
+ using (mockery.Record()) {
+ Expect
+ .Call(factory.CreateFor(GetType()))
+ .Return(logger)
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ Log.For(this);
+ }
+ }
+ }
+}
\ No newline at end of file diff --git a/src/Notepad/Infrastructure/System/IApplicationEnvironment.cs b/src/Notepad/Infrastructure/System/IApplicationEnvironment.cs new file mode 100644 index 0000000..64cc737 --- /dev/null +++ b/src/Notepad/Infrastructure/System/IApplicationEnvironment.cs @@ -0,0 +1,13 @@ +using System;
+
+namespace Notepad.Infrastructure.System {
+ public interface IApplicationEnvironment {
+ void ShutDown();
+ }
+
+ public class ApplicationEnvironment : IApplicationEnvironment {
+ public void ShutDown() {
+ Environment.Exit(Environment.ExitCode);
+ }
+ }
+}
\ No newline at end of file |
