diff --git a/Source/Bifrost.Silverlight/Bifrost.Silverlight.csproj b/Source/Bifrost.Silverlight/Bifrost.Silverlight.csproj index 699fb0d66..c7ba63d9d 100644 --- a/Source/Bifrost.Silverlight/Bifrost.Silverlight.csproj +++ b/Source/Bifrost.Silverlight/Bifrost.Silverlight.csproj @@ -626,6 +626,9 @@ Execution\ITypeDiscoverer.cs + + Execution\ITypeFinder.cs + Execution\ITypeImporter.cs @@ -644,6 +647,9 @@ Execution\TypeDiscoverer.cs + + Execution\TypeFinder.cs + Execution\TypeImporter.cs diff --git a/Source/Bifrost.Specs/Bifrost.Specs.csproj b/Source/Bifrost.Specs/Bifrost.Specs.csproj index 982d86bd6..ee3b4e6a2 100644 --- a/Source/Bifrost.Specs/Bifrost.Specs.csproj +++ b/Source/Bifrost.Specs/Bifrost.Specs.csproj @@ -331,6 +331,13 @@ + + + + + + + @@ -722,7 +729,6 @@ - diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/given/a_type_discoverer.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/given/a_type_discoverer.cs index cb15b9bd8..001cad33f 100644 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/given/a_type_discoverer.cs +++ b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/given/a_type_discoverer.cs @@ -1,4 +1,7 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; using Bifrost.Execution; using Machine.Specifications; using Moq; @@ -7,14 +10,32 @@ namespace Bifrost.Specs.Execution.for_TypeDiscoverer.given { public class a_type_discoverer { - protected static TypeDiscoverer TypeDiscoverer; + protected static TypeDiscoverer type_discoverer; + protected static Mock<_Assembly> assembly_mock; + protected static Type[] types; + + protected static Mock assemblies_mock; + protected static Mock type_finder_mock; Establish context = () => { - var assembliesMock = new Mock(); - assembliesMock.Setup(x => x.GetAll()).Returns(new[] - {typeof (a_type_discoverer).Assembly}); - TypeDiscoverer = new TypeDiscoverer(assembliesMock.Object); + types = new[] { + typeof(ISingle), + typeof(Single), + typeof(IMultiple), + typeof(FirstMultiple), + typeof(SecondMultiple) + }; + + assembly_mock = new Mock<_Assembly>(); + assembly_mock.Setup(a => a.GetTypes()).Returns(types); + assembly_mock.Setup(a => a.FullName).Returns("A.Full.Name"); + + assemblies_mock = new Mock(); + assemblies_mock.Setup(x => x.GetAll()).Returns(new[] { assembly_mock.Object }); + + type_finder_mock = new Mock(); + type_discoverer = new TypeDiscoverer(assemblies_mock.Object, type_finder_mock.Object); }; } } diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_does_not_exist.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_does_not_exist.cs index 7624f9af2..8dac029ee 100644 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_does_not_exist.cs +++ b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_does_not_exist.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Bifrost.Execution; using Machine.Specifications; @@ -7,9 +8,12 @@ namespace Bifrost.Specs.Execution.for_TypeDiscoverer [Subject(typeof(TypeDiscoverer))] public class when_finding_type_by_name_that_does_not_exist : given.a_type_discoverer { - static Type typeFound; - Because of = () => typeFound = TypeDiscoverer.FindTypeByFullName(typeof(Single).FullName + "Blah"); + static Type type_found; - It should_be_null = () => typeFound.ShouldBeNull(); + Establish context = () => type_finder_mock.Setup(t => t.FindTypeByFullName(Moq.It.IsAny>(), Moq.It.IsAny())).Returns((Type)null); + + Because of = () => type_found = type_discoverer.FindTypeByFullName(typeof(Single).FullName + "Blah"); + + It should_be_null = () => type_found.ShouldBeNull(); } } \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_exists.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_exists.cs index 947ce47dd..a94fefaaa 100644 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_exists.cs +++ b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_type_by_name_that_exists.cs @@ -8,7 +8,7 @@ namespace Bifrost.Specs.Execution.for_TypeDiscoverer public class when_finding_type_by_name_that_exists : given.a_type_discoverer { static Type typeFound; - Because of = () => typeFound = TypeDiscoverer.FindTypeByFullName(typeof(Single).FullName); + Because of = () => typeFound = type_discoverer.FindTypeByFullName(typeof(Single).FullName); It should_not_return_null = () => typeFound.ShouldNotBeNull(); It should_return_the_correct_type = () => typeFound.ShouldEqual(typeof(Single)); diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations.cs index dc21d463b..fb7ea6a7d 100644 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations.cs +++ b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Bifrost.Execution; using Machine.Specifications; @@ -7,11 +8,13 @@ namespace Bifrost.Specs.Execution.for_TypeDiscoverer [Subject(typeof(TypeDiscoverer))] public class when_finding_types_with_multiple_implementations : given.a_type_discoverer { - static Type[] typesFound; - Because we_find_multiple = () => typesFound = TypeDiscoverer.FindMultiple(); + static IEnumerable types_found; - It should_not_return_null = () => typesFound.ShouldNotBeNull(); - It should_return_2_types = () => typesFound.Length.ShouldEqual(2); - It should_contain_the_expected_types = () => typesFound.ShouldContain(typeof (FirstMultiple), typeof (SecondMultiple)); + Establish context = () => type_finder_mock.Setup(t => t.FindMultiple(Moq.It.IsAny>())).Returns(new[] { typeof(FirstMultiple), typeof(SecondMultiple) }); + + Because of = () => types_found = type_discoverer.FindMultiple(); + + It should_not_return_null = () => types_found.ShouldNotBeNull(); + It should_contain_the_types_found_by_the_finder = () => types_found.ShouldContain(typeof (FirstMultiple), typeof (SecondMultiple)); } } \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs deleted file mode 100644 index 68f48ccde..000000000 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Bifrost.Execution; -using Machine.Specifications; - -namespace Bifrost.Specs.Execution.for_TypeDiscoverer -{ - [Subject(typeof(TypeDiscoverer))] - public class when_finding_types_with_multiple_implementations_but_asking_for_a_single : given.a_type_discoverer - { - static Exception Exception; - Because we_ask_for_a_single = () => Exception = Catch.Exception(() => TypeDiscoverer.FindSingle()); - - It should_throw_an_ArgumentException = () => Exception.ShouldBeOfExactType(); - } -} \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_only_one_implementation.cs b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_only_one_implementation.cs index 3e294213a..f7d87e64d 100644 --- a/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_only_one_implementation.cs +++ b/Source/Bifrost.Specs/Execution/for_TypeDiscoverer/when_finding_types_with_only_one_implementation.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Bifrost.Execution; using Machine.Specifications; @@ -8,7 +9,10 @@ namespace Bifrost.Specs.Execution.for_TypeDiscoverer public class when_finding_types_with_only_one_implementation : given.a_type_discoverer { static Type typeFound; - Because we_find_single = () => typeFound = TypeDiscoverer.FindSingle(); + + Establish context = () => type_finder_mock.Setup(t => t.FindSingle(Moq.It.IsAny>())).Returns(typeof(Single)); + + Because we_find_single = () => typeFound = type_discoverer.FindSingle(); It should_not_return_null = () => typeFound.ShouldNotBeNull(); It should_return_correct_implementation_when = () => typeFound.ShouldEqual(typeof (Single)); diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/Stubs.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/Stubs.cs new file mode 100644 index 000000000..7dbac15f4 --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/Stubs.cs @@ -0,0 +1,27 @@ +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + public interface ISingle + { + + } + + public class Single : ISingle + { + + } + + public interface IMultiple + { + + } + + public class FirstMultiple : IMultiple + { + + } + + public class SecondMultiple : IMultiple + { + + } +} diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/given/a_type_finder.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/given/a_type_finder.cs new file mode 100644 index 000000000..7b7a100c7 --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/given/a_type_finder.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder.given +{ + public class a_type_finder + { + protected static TypeFinder type_finder; + protected static IEnumerable types; + + Establish context = () => + { + types = new[] { + typeof(ISingle), + typeof(Single), + typeof(IMultiple), + typeof(FirstMultiple), + typeof(SecondMultiple) + }; + type_finder = new TypeFinder(); + }; + } +} diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_does_not_exist.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_does_not_exist.cs new file mode 100644 index 000000000..3ec64ffd6 --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_does_not_exist.cs @@ -0,0 +1,16 @@ +using System; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + [Subject(typeof(TypeFinder))] + public class when_finding_type_by_name_that_does_not_exist : given.a_type_finder + { + static Exception exception; + + Because of = () => exception = Catch.Exception(() => type_finder.FindTypeByFullName(types, typeof(Single).FullName + "Blah")); + + It should_be_throw_unable_to_resolve_type_by_name = () => exception.ShouldBeOfExactType(); + } +} \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_exists.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_exists.cs new file mode 100644 index 000000000..ab9a0620f --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_type_by_name_that_exists.cs @@ -0,0 +1,17 @@ +using System; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + [Subject(typeof(TypeFinder))] + public class when_finding_type_by_name_that_exists : given.a_type_finder + { + static Type type_found; + + Because of = () => type_found = type_finder.FindTypeByFullName(types, typeof(Single).FullName); + + It should_not_return_null = () => type_found.ShouldNotBeNull(); + It should_return_the_correct_type = () => type_found.ShouldEqual(typeof(Single)); + } +} \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations.cs new file mode 100644 index 000000000..5e65707dc --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + [Subject(typeof(TypeFinder))] + public class when_finding_types_with_multiple_implementations : given.a_type_finder + { + static IEnumerable types_found; + + Because of = () => types_found = type_finder.FindMultiple(types); + + It should_not_return_null = () => types_found.ShouldNotBeNull(); + It should_contain_the_expected_types = () => types_found.ShouldContain(typeof (FirstMultiple), typeof (SecondMultiple)); + } +} \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs new file mode 100644 index 000000000..75928a8b8 --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_multiple_implementations_but_asking_for_a_single.cs @@ -0,0 +1,16 @@ +using System; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + [Subject(typeof(TypeFinder))] + public class when_finding_types_with_multiple_implementations_but_asking_for_a_single : given.a_type_finder + { + static Exception exception; + + Because of = () => exception = Catch.Exception(() => type_finder.FindSingle(types)); + + It should_throw_an_ArgumentException = () => exception.ShouldBeOfExactType(); + } +} \ No newline at end of file diff --git a/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_only_one_implementation.cs b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_only_one_implementation.cs new file mode 100644 index 000000000..6fa01f4c0 --- /dev/null +++ b/Source/Bifrost.Specs/Execution/for_TypeFinder/when_finding_types_with_only_one_implementation.cs @@ -0,0 +1,17 @@ +using System; +using Bifrost.Execution; +using Machine.Specifications; + +namespace Bifrost.Specs.Execution.for_TypeFinder +{ + [Subject(typeof(TypeFinder))] + public class when_finding_types_with_only_one_implementation : given.a_type_finder + { + static Type type_found; + + Because of = () => type_found = type_finder.FindSingle(types); + + It should_not_return_null = () => type_found.ShouldNotBeNull(); + It should_return_correct_implementation_when = () => type_found.ShouldEqual(typeof (Single)); + } +} \ No newline at end of file diff --git a/Source/Bifrost.Web/Services/JsonInterceptor.cs b/Source/Bifrost.Web/Services/JsonInterceptor.cs index 1d92757e2..f4c183721 100644 --- a/Source/Bifrost.Web/Services/JsonInterceptor.cs +++ b/Source/Bifrost.Web/Services/JsonInterceptor.cs @@ -3,13 +3,14 @@ using Newtonsoft.Json.Linq; using System; using System.Linq; +using System.Collections.Generic; namespace Bifrost.Web.Services { [Singleton] public class JsonInterceptor : IJsonInterceptor { - private readonly Type[] _valueInterceptors; + private readonly IEnumerable _valueInterceptors; private readonly IContainer _container; public JsonInterceptor(ITypeDiscoverer typeDiscoverer, IContainer container) diff --git a/Source/Bifrost/Bifrost.csproj b/Source/Bifrost/Bifrost.csproj index 6cc721ee5..ddfd14094 100644 --- a/Source/Bifrost/Bifrost.csproj +++ b/Source/Bifrost/Bifrost.csproj @@ -159,12 +159,14 @@ - + + + diff --git a/Source/Bifrost/Configuration/Defaults/DefaultBindings.cs b/Source/Bifrost/Configuration/Defaults/DefaultBindings.cs index b5b699c27..183584bc0 100644 --- a/Source/Bifrost/Configuration/Defaults/DefaultBindings.cs +++ b/Source/Bifrost/Configuration/Defaults/DefaultBindings.cs @@ -51,6 +51,7 @@ public void Initialize(IContainer container) container.Bind(_assemblyProvider); container.Bind(typeof(global::Bifrost.Execution.Assemblies), BindingLifecycle.Singleton); container.Bind(typeof(TypeDiscoverer), BindingLifecycle.Singleton); + container.Bind(typeof(TypeFinder), BindingLifecycle.Singleton); } #pragma warning restore 1591 // Xml Comments } diff --git a/Source/Bifrost/Execution/ExecutionContextDetailsPopulator.cs b/Source/Bifrost/Execution/ExecutionContextDetailsPopulator.cs index 704d8de67..14d0428ab 100644 --- a/Source/Bifrost/Execution/ExecutionContextDetailsPopulator.cs +++ b/Source/Bifrost/Execution/ExecutionContextDetailsPopulator.cs @@ -16,8 +16,9 @@ // limitations under the License. // #endregion - using System; +using System.Collections.Generic; + namespace Bifrost.Execution { /// @@ -27,7 +28,7 @@ public class ExecutionContextDetailsPopulator : IExecutionContextDetailsPopulato { ITypeDiscoverer _typeDiscoverer; IContainer _container; - Type[] _populatorTypes; + IEnumerable _populatorTypes; /// /// Initializes an instance of diff --git a/Source/Bifrost/Execution/ICanFilterAssembly.cs b/Source/Bifrost/Execution/ICanSpecifyAssemblies.cs similarity index 68% rename from Source/Bifrost/Execution/ICanFilterAssembly.cs rename to Source/Bifrost/Execution/ICanSpecifyAssemblies.cs index d5cc6b7d7..d1ae68f63 100644 --- a/Source/Bifrost/Execution/ICanFilterAssembly.cs +++ b/Source/Bifrost/Execution/ICanSpecifyAssemblies.cs @@ -16,13 +16,12 @@ // limitations under the License. // #endregion -using System.Reflection; -using System.Runtime.InteropServices; +using Bifrost.Configuration.Assemblies; namespace Bifrost.Execution { /// - /// Defines something that tell wether or not to filter away an assembly. + /// Specifies what assemblies to include /// /// /// Typically used by implementations of to @@ -30,14 +29,12 @@ namespace Bifrost.Execution /// which relies on knowing about assemblies /// to be able to discover types. /// - public interface ICanFilterAssembly + public interface ICanSpecifyAssemblies { /// - /// Method that gets called participating in the chain to decide wether or - /// not an assembly should be included + /// Method that gets called for specifying which assemblies to include or not /// - /// to check - /// True if it should be included, false if not - bool ShouldInclude(_Assembly assembly); + /// object to specfiy on + void Specify(AssembliesConfiguration configuration); } } diff --git a/Source/Bifrost/Execution/ITypeDiscoverer.cs b/Source/Bifrost/Execution/ITypeDiscoverer.cs index 2b3d8f485..48ec63cde 100644 --- a/Source/Bifrost/Execution/ITypeDiscoverer.cs +++ b/Source/Bifrost/Execution/ITypeDiscoverer.cs @@ -53,7 +53,7 @@ public interface ITypeDiscoverer /// If the base type is an interface, it will look for any types implementing the interface. /// If it is a class, it will find anyone inheriting from that class /// - Type[] FindMultiple(); + IEnumerable FindMultiple(); /// /// Find a single implementation of a basetype @@ -76,7 +76,7 @@ public interface ITypeDiscoverer /// If the base type is an interface, it will look for any types implementing the interface. /// If it is a class, it will find anyone inheriting from that class /// - Type[] FindMultiple(Type type); + IEnumerable FindMultiple(Type type); /// /// Find a single type using the full name, without assembly diff --git a/Source/Bifrost/Execution/ITypeFinder.cs b/Source/Bifrost/Execution/ITypeFinder.cs new file mode 100644 index 000000000..dbfafbdaf --- /dev/null +++ b/Source/Bifrost/Execution/ITypeFinder.cs @@ -0,0 +1,87 @@ +#region License +// +// Copyright (c) 2008-2015, Dolittle (http://www.dolittle.com) +// +// Licensed under the MIT License (http://opensource.org/licenses/MIT) +// +// You may not use this file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://github.com/dolittle/Bifrost/blob/master/MIT-LICENSE.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion +using System; +using System.Collections.Generic; + +namespace Bifrost.Execution +{ + /// + /// Defines a system that is capable of finding types based on base types + /// + public interface ITypeFinder + { + /// + /// Find a single implementation of a basetype + /// + /// Types to find from + /// Basetype to find for + /// Type found + /// + /// If the base type is an interface, it will look for any types implementing the interface. + /// If it is a class, it will find anyone inheriting from that class + /// + /// If there is more than one instance found + Type FindSingle(IEnumerable types); + + /// + /// Find multiple implementations of a basetype + /// + /// Types to find from + /// Basetype to find for + /// All types implementing or inheriting from the given basetype + /// + /// If the base type is an interface, it will look for any types implementing the interface. + /// If it is a class, it will find anyone inheriting from that class + /// + IEnumerable FindMultiple(IEnumerable types); + + /// + /// Find a single implementation of a basetype + /// + /// Types to find from + /// Basetype to find for + /// Type found + /// + /// If the base type is an interface, it will look for any types implementing the interface. + /// If it is a class, it will find anyone inheriting from that class + /// + /// If there is more than one instance found + Type FindSingle(IEnumerable types, Type type); + + /// + /// Find multiple implementations of a basetype + /// + /// Types to find from + /// Basetype to find for + /// All types implementing or inheriting from the given basetype + /// + /// If the base type is an interface, it will look for any types implementing the interface. + /// If it is a class, it will find anyone inheriting from that class + /// + IEnumerable FindMultiple(IEnumerable types, Type type); + + /// + /// Find a single type using the full name, without assembly + /// + /// Types to find from + /// full name of the type to find + /// The type is found, null otherwise + Type FindTypeByFullName(IEnumerable types, string fullName); + } +} diff --git a/Source/Bifrost/Execution/TypeDiscoverer.cs b/Source/Bifrost/Execution/TypeDiscoverer.cs index bb6dbde19..511d33533 100644 --- a/Source/Bifrost/Execution/TypeDiscoverer.cs +++ b/Source/Bifrost/Execution/TypeDiscoverer.cs @@ -42,15 +42,14 @@ public class TypeDiscoverer : ITypeDiscoverer static List NamespaceStartingWithExclusions = new List(); IAssemblies _assemblies; + ITypeFinder _typeFinder; #if(SILVERLIGHT || WINDOWS_PHONE) - Dictionary> _types; + List _types; #else - ConcurrentDictionary> _types; + ConcurrentBag _types; #endif - IDictionary _implementingTypes; - /// /// Exclude discovering of types in a specific namespace /// @@ -63,17 +62,18 @@ public static void ExcludeNamespaceStartingWith(string name) /// /// Initializes a new instance of TypeDiscoverer /// - public TypeDiscoverer(IAssemblies assemblies) + /// for getting assemblies + /// for finding types from all collected types + public TypeDiscoverer(IAssemblies assemblies, ITypeFinder typeFinder) { _assemblies = assemblies; + _typeFinder = typeFinder; #if(SILVERLIGHT) - _types = new Dictionary>(); + _types = new List(); #else - _types = new ConcurrentDictionary>(); + _types = new ConcurrentBag(); #endif - - _implementingTypes = new Dictionary(); CollectTypes(); } @@ -81,90 +81,41 @@ public TypeDiscoverer(IAssemblies assemblies) #pragma warning disable 1591 // Xml Comments public IEnumerable GetAll() { - return _types.Values.SelectMany(x => x.Values.ToList()); + return _types; } public Type FindSingle() { - var type = FindSingle(typeof(T)); - return type; + return _typeFinder.FindSingle(_types); } - public Type[] FindMultiple() + public IEnumerable FindMultiple() { - var types = FindMultiple(typeof(T)); - return types; + return _typeFinder.FindMultiple(_types); } public Type FindSingle(Type type) { - var typesFound = Find(type); - - if (typesFound.Length > 1) - throw new MultipleTypesFoundException(string.Format("More than one type found for '{0}'", type.FullName)); - return typesFound.SingleOrDefault(); + return _typeFinder.FindSingle(_types, type); } - public Type[] FindMultiple(Type type) + public IEnumerable FindMultiple(Type type) { - var typesFound = Find(type); - return typesFound; + return _typeFinder.FindMultiple(_types, type); } public Type FindTypeByFullName(string fullName) { - if (!_types.ContainsKey(fullName)) return null; - - var match = _types[fullName].Values; - - if (match.Count > 1) - { - throw new UnableToResolveTypeByName(fullName); - } - - return match.First(); + return _typeFinder.FindTypeByFullName(_types, fullName); } #pragma warning restore 1591 // Xml Comments -#if(SILVERLIGHT || WINDOWS_PHONE) - - void AddTypes(IEnumerable types) - { - foreach (var type in types) - { - if (_types.ContainsKey(type.FullName)) - { - var entry = _types[type.Assembly.FullName]; - entry[type.Assembly.FullName] = type; - } - else - { - _types.Add(type.FullName, new Dictionary {{type.Assembly.FullName, type}}); - } - } - } - -#else - void AddTypes(IEnumerable types) { - foreach (var type in types) - { - if (!_types.TryAdd(type.FullName, new Dictionary { { type.Assembly.FullName, type } })) - { - var entry = _types[type.FullName]; - - lock (entry) - { - entry[type.Assembly.FullName] = type; - } - } - - } + types.ForEach(_types.Add); } -#endif #if(WINDOWS_PHONE) void CollectTypes() @@ -245,32 +196,5 @@ static bool NameStartsWithAnExcludedNamespace(string name) { return NamespaceStartingWithExclusions.Any(name.StartsWith); } - - Type[] Find(Type type) - { - Type[] typesFound; - - Func isAssignableFrom = (t1, t2) => t2.IsAssignableFrom(t1); - if (type.IsInterface) isAssignableFrom = (t1, t2) => t1.HasInterface(t2); - - if (!_implementingTypes.TryGetValue(type, out typesFound)) - { - var query = from t in _types.Values.SelectMany(a => a.Values) - where - isAssignableFrom(t,type) && -#if(NETFX_CORE) - !t.GetTypeInfo().IsInterface && - !t.GetTypeInfo().IsAbstract -#else - !t.IsInterface && - !t.IsAbstract -#endif - select t; - typesFound = query.ToArray(); - _implementingTypes[type] = typesFound; - } - - return typesFound; - } } } diff --git a/Source/Bifrost/Execution/TypeFinder.cs b/Source/Bifrost/Execution/TypeFinder.cs new file mode 100644 index 000000000..418a702ad --- /dev/null +++ b/Source/Bifrost/Execution/TypeFinder.cs @@ -0,0 +1,99 @@ +#region License +// +// Copyright (c) 2008-2015, Dolittle (http://www.dolittle.com) +// +// Licensed under the MIT License (http://opensource.org/licenses/MIT) +// +// You may not use this file except in compliance with the License. +// You may obtain a copy of the license at +// +// http://github.com/dolittle/Bifrost/blob/master/MIT-LICENSE.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +#if(SILVERLIGHT) +using System.Windows; +#endif +using Bifrost.Extensions; + +namespace Bifrost.Execution +{ + /// + /// Represents an implementation of + /// + public class TypeFinder : ITypeFinder + { +#pragma warning disable 1591 // Xml Comments + public Type FindSingle(IEnumerable types) + { + var type = FindSingle(types, typeof(T)); + return type; + } + + public IEnumerable FindMultiple(IEnumerable types) + { + var typesFound = FindMultiple(types, typeof(T)); + return typesFound; + } + + public Type FindSingle(IEnumerable types, Type type) + { + var typesFound = Find(types, type); + ThrowIfMultipleTypesFound(type, typesFound); + return typesFound.SingleOrDefault(); + } + + public IEnumerable FindMultiple(IEnumerable types, Type type) + { + var typesFound = Find(types, type); + return typesFound; + } + + public Type FindTypeByFullName(IEnumerable types, string fullName) + { + var typeFound = types.Where(t => t.FullName == fullName).SingleOrDefault(); + ThrowIfTypeNotFound(fullName, typeFound); + return typeFound; + } +#pragma warning restore 1591 // Xml Comments + Type[] Find(IEnumerable types, Type type) + { + Func isAssignableFrom = (t1, t2) => t2.IsAssignableFrom(t1); + if (type.IsInterface) isAssignableFrom = (t1, t2) => t1.HasInterface(t2); + + var query = types.Where( + t=>isAssignableFrom(t,type) && +#if(NETFX_CORE) + !t.GetTypeInfo().IsInterface && + !t.GetTypeInfo().IsAbstract + +#else + !t.IsInterface && + !t.IsAbstract +#endif + ); + + var typesFound = query.ToArray(); + return typesFound; + } + + void ThrowIfMultipleTypesFound(Type type, Type[] typesFound) + { + if (typesFound.Length > 1) + throw new MultipleTypesFoundException(string.Format("More than one type found for '{0}'", type.FullName)); + } + + void ThrowIfTypeNotFound(string fullName, Type typeFound) + { + if (typeFound == null) throw new UnableToResolveTypeByName(fullName); + } + } +} diff --git a/Source/Bifrost/Execution/TypeImporter.cs b/Source/Bifrost/Execution/TypeImporter.cs index 54750a6a8..3021e960c 100644 --- a/Source/Bifrost/Execution/TypeImporter.cs +++ b/Source/Bifrost/Execution/TypeImporter.cs @@ -17,6 +17,8 @@ // #endregion using System; +using System.Collections.Generic; +using System.Linq; namespace Bifrost.Execution { @@ -46,26 +48,19 @@ public T[] ImportMany() try { var types = _typeDiscoverer.FindMultiple(); - if( types == null ) - { - throw new ArgumentException( - string.Format("Can't import type {0}, it was not discovered", typeof(T))); - } - var instances = new T[types.Length]; - for (var instanceIndex = 0; instanceIndex < types.Length; instanceIndex++) - { - instances[instanceIndex] = (T) _container.Get(types[instanceIndex]); - } - + ThrowIfTypeCanNotBeImported(typeof(T), types); + var instances = types.Select(t => (T)_container.Get(t)).ToArray(); return instances; } catch (ArgumentException innerException) { - throw new ArgumentException( - string.Format("Can't import type {0}, see inner exception for details", typeof(T)), innerException); + ThrowUnableToImportType(typeof(T),innerException); } + return new T[0]; } + + public T Import() { try @@ -78,16 +73,33 @@ public T Import() } else { - throw new ArgumentException( - string.Format("Can't import type {0}, it was not discovered", typeof(T))); + ThrowCanNotBeImported(typeof(T)); } } catch (ArgumentException innerException) { - throw new ArgumentException( - string.Format("Can't import type {0}, see inner exception for details", typeof(T)), innerException); + ThrowUnableToImportType(typeof(T), innerException); } + return default(T); } #pragma warning restore 1591 // Xml Comments + + void ThrowUnableToImportType(Type type, ArgumentException innerException) + { + throw new ArgumentException( + string.Format("Can't import type {0}, see inner exception for details", type), innerException); + } + + void ThrowIfTypeCanNotBeImported(Type type, IEnumerable types) + { + if (types == null) ThrowCanNotBeImported(type); + } + + void ThrowCanNotBeImported(Type type) + { + throw new ArgumentException( + string.Format("Can't import type {0}, it was not discovered", type)); + } + } } \ No newline at end of file diff --git a/Source/Bifrost/Execution/UnableToResolveTypeByName.cs b/Source/Bifrost/Execution/UnableToResolveTypeByName.cs index 01d598ecb..edf819eab 100644 --- a/Source/Bifrost/Execution/UnableToResolveTypeByName.cs +++ b/Source/Bifrost/Execution/UnableToResolveTypeByName.cs @@ -29,7 +29,7 @@ public class UnableToResolveTypeByName : ArgumentException /// Initializes an instance of /// /// - public UnableToResolveTypeByName(string typeName) : base(string.Format("Unable to resolve '{0}'. More than one type found with the current name'", typeName)) + public UnableToResolveTypeByName(string typeName) : base(string.Format("Unable to resolve '{0}'.", typeName)) { } diff --git a/Source/Bifrost/Read/ReadModelFilters.cs b/Source/Bifrost/Read/ReadModelFilters.cs index 4bd9e2bd3..ff4faf502 100644 --- a/Source/Bifrost/Read/ReadModelFilters.cs +++ b/Source/Bifrost/Read/ReadModelFilters.cs @@ -18,6 +18,7 @@ #endregion using System; using System.Collections.Generic; +using System.Linq; using Bifrost.Execution; namespace Bifrost.Read @@ -28,7 +29,7 @@ namespace Bifrost.Read public class ReadModelFilters : IReadModelFilters { IContainer _container; - Type[] _filterTypes; + IEnumerable _filterTypes; /// /// Initializes an instance of @@ -45,7 +46,7 @@ public ReadModelFilters(ITypeDiscoverer typeDiscoverer, IContainer container) #pragma warning disable 1591 public IEnumerable Filter(IEnumerable readModels) { - if (_filterTypes.Length == 0) return readModels; + if (_filterTypes.Count() == 0) return readModels; foreach (var filterType in _filterTypes) {