diff --git a/Nuclex.Support (Xbox 360).csproj b/Nuclex.Support (Xbox 360).csproj
index 8fb3d0c..c02e09e 100644
--- a/Nuclex.Support (Xbox 360).csproj
+++ b/Nuclex.Support (Xbox 360).csproj
@@ -118,11 +118,31 @@
ReverseComparer.cs
+
+
+ PrototypeFactory.cs
+
+
+
+ AppDomainTypeLister.cs
+
+
+
+ AssemblyTypeLister.cs
+
+
+
+ PredefinedTypeLister.cs
+
-
+
+
+
+ RepositoryTypeLister.cs
+
ServiceManager.cs
@@ -233,6 +253,10 @@
ThreadOperation.cs
+
+ ServiceManager.cs
+
+
Shared.cs
diff --git a/Nuclex.Support.csproj b/Nuclex.Support.csproj
index d57b184..7bdb582 100644
--- a/Nuclex.Support.csproj
+++ b/Nuclex.Support.csproj
@@ -100,11 +100,31 @@
ReverseComparer.cs
+
+
+ PrototypeFactory.cs
+
+
+
+ AppDomainTypeLister.cs
+
+
+
+ AssemblyTypeLister.cs
+
+
+
+ PredefinedTypeLister.cs
+
-
+
+
+
+ RepositoryTypeLister.cs
+
ServiceManager.cs
@@ -215,6 +235,10 @@
ThreadOperation.cs
+
+ ServiceManager.cs
+
+
Shared.cs
diff --git a/Source/Plugins/PrototypeFactory.Test.cs b/Source/Plugins/PrototypeFactory.Test.cs
new file mode 100644
index 0000000..cec4088
--- /dev/null
+++ b/Source/Plugins/PrototypeFactory.Test.cs
@@ -0,0 +1,141 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Plugins {
+
+ /// Unit Test for the prototype-based factory class
+ [TestFixture]
+ public class PrototypeFactoryTest {
+
+ #region interface IProduct
+
+ /// Interface used for the product in the unit test
+ private interface IProduct {
+ /// Some value associated with the product
+ int Value { get; }
+ }
+
+ #endregion // interface IProduct
+
+ #region class ConcretePrototype
+
+ ///
+ /// Class derived from the abstract base to serve as concrete product for
+ /// testing the factory employer
+ ///
+ private class ConcretePrototype : IProduct, ICloneable, IDisposable {
+
+ /// Initializes a new instance of the prototype product
+ /// Value that will be associated with this instance
+ public ConcretePrototype(int value) {
+ this.value = value;
+ }
+
+ /// Immediately releases all resources owned by the instance
+ public void Dispose() {
+ this.disposed = true;
+ }
+
+ /// Value the product has been associated with
+ public int Value { get { return this.value; } }
+
+ /// Whether the prototype instance has been disposed
+ public bool IsDisposed {
+ get { return this.disposed; }
+ }
+
+ /// Creates an identical copy of the instance
+ /// An identical copy of the instance
+ object ICloneable.Clone() {
+ return new ConcretePrototype(this.value);
+ }
+
+ /// Value associated with the product
+ private int value;
+ /// Whether the instance has been disposed
+ private bool disposed;
+
+ }
+
+ #endregion // class ConcretePrototype
+
+ ///
+ /// Tests whether the prototype-based factory behaves correctly by creating
+ /// new instances of its product using clones of its assigned prototype.
+ ///
+ [Test]
+ public void TestGenericInstanceCreation() {
+ ConcretePrototype template = new ConcretePrototype(42);
+
+ IAbstractFactory factory = new PrototypeFactory<
+ IProduct, ConcretePrototype
+ >(template);
+
+ IProduct factoryCreatedProduct = factory.CreateInstance();
+
+ Assert.AreEqual(template.Value, factoryCreatedProduct.Value);
+ }
+
+ ///
+ /// Tests whether the prototype-based factory behaves correctly by creating
+ /// new instances of its product using clones of its assigned prototype.
+ ///
+ [Test]
+ public void TestInstanceCreation() {
+ ConcretePrototype template = new ConcretePrototype(42);
+
+ IAbstractFactory factory = new PrototypeFactory<
+ IProduct, ConcretePrototype
+ >(template);
+
+ IProduct factoryCreatedProduct = (IProduct)factory.CreateInstance();
+
+ Assert.AreEqual(template.Value, factoryCreatedProduct.Value);
+ }
+
+ ///
+ /// Tests whether the prototype is disposed if it implements the IDisposable
+ /// interface and the factory is explicitely disposed.
+ ///
+ [Test]
+ public void TestPrototypeDisposal() {
+ ConcretePrototype template = new ConcretePrototype(42);
+
+ PrototypeFactory factory = new PrototypeFactory<
+ IProduct, ConcretePrototype
+ >(template);
+
+ Assert.IsFalse(template.IsDisposed);
+ factory.Dispose();
+ Assert.IsTrue(template.IsDisposed);
+ }
+
+ }
+
+} // namespace Nuclex.Support.Plugins
+
+#endif // UNITTEST
diff --git a/Source/Plugins/PrototypeFactory.cs b/Source/Plugins/PrototypeFactory.cs
new file mode 100644
index 0000000..d40dc8b
--- /dev/null
+++ b/Source/Plugins/PrototypeFactory.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Nuclex.Support.Plugins {
+
+ /// Factory that creates instances by cloning a prototype
+ /// Type of product created by the factory
+ /// Type of the prototype that will be cloned
+ public class PrototypeFactory :
+ IAbstractFactory, IAbstractFactory, IDisposable
+ where ProductType : class
+ where ConcreteType : class, ICloneable {
+
+ /// Initializes a new prototype based factory
+ /// Prototype instance that will be cloned
+ public PrototypeFactory(ConcreteType prototype) {
+ this.prototype = prototype;
+ }
+
+ ///
+ /// Creates a new instance of the type to which the factory is specialized
+ ///
+ /// The newly created instance
+ public ProductType CreateInstance() {
+ return (ProductType)this.prototype.Clone();
+ }
+
+ ///
+ /// Creates a new instance of the type to which the factory is specialized
+ ///
+ /// The newly created instance
+ object IAbstractFactory.CreateInstance() {
+ return this.prototype.Clone();
+ }
+
+ /// Immediately releases all resources owned by the instance
+ public void Dispose() {
+ if(this.prototype != null) {
+ IDisposable disposablePrototype = this.prototype as IDisposable;
+ if(disposablePrototype != null) {
+ disposablePrototype.Dispose();
+ }
+
+ this.prototype = null;
+ }
+ }
+
+ /// The prototype object
+ private ConcreteType prototype;
+
+ }
+
+} // namespace Nuclex.Support.Plugins
diff --git a/Source/Services/AppDomainTypeLister.Test.cs b/Source/Services/AppDomainTypeLister.Test.cs
new file mode 100644
index 0000000..827c2d5
--- /dev/null
+++ b/Source/Services/AppDomainTypeLister.Test.cs
@@ -0,0 +1,73 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Services {
+
+ /// Unit Test for the cached app domain type lister
+ [TestFixture]
+ public class AppDomainTypeListerTest {
+
+ ///
+ /// Verifies that the assembly type list is generated correctly for
+ /// the default constructor (using the calling app domain)
+ ///
+ [Test]
+ public void TestDefaultConstructur() {
+ AppDomainTypeLister testLister = new AppDomainTypeLister();
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(AppDomainTypeListerTest)).And.Member(typeof(Assembly))
+ );
+ }
+
+ ///
+ /// Verifies that the assembly type list is generated correctly for
+ /// the full constructor
+ ///
+ [Test]
+ public void TestFullConstructur() {
+ AppDomain newAppDomain = AppDomain.CreateDomain("AppDomainTypeListerTest.Domain");
+ try {
+ AppDomainTypeLister testLister = new AppDomainTypeLister(newAppDomain);
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(Assembly)).And.No.Member(typeof(AppDomainTypeListerTest))
+ );
+ }
+ finally {
+ AppDomain.Unload(newAppDomain);
+ }
+ }
+
+ }
+
+} // namespace Nuclex.Support.Services
+
+#endif // UNITTEST
diff --git a/Source/Services/AppDomainTypeLister.cs b/Source/Services/AppDomainTypeLister.cs
new file mode 100644
index 0000000..42c3c4c
--- /dev/null
+++ b/Source/Services/AppDomainTypeLister.cs
@@ -0,0 +1,59 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Nuclex.Support.Services {
+
+#if !XBOX360
+
+ /// Lists the types of all assemblies in an application domain
+ public class AppDomainTypeLister : AssemblyTypeLister {
+
+ ///
+ /// Initializes a new application domain type lister using the application domain
+ /// of the calling method
+ ///
+ public AppDomainTypeLister() : this(AppDomain.CurrentDomain) { }
+
+ /// Initializes a new application domain type lister
+ /// Application domain whose types will be listed
+ public AppDomainTypeLister(AppDomain appDomain) {
+ this.appDomain = appDomain;
+ }
+
+ ///
+ /// Obtains an enumerable list of all assemblies in the application domain
+ ///
+ /// An enumerable list of the assemblies in the application domain
+ protected override IEnumerable GetAssemblies() {
+ return this.appDomain.GetAssemblies();
+ }
+
+ /// Application domain whose types the lister works on
+ private AppDomain appDomain;
+
+ }
+
+#endif // !XBOX360
+
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/AssemblyTypeLister.Test.cs b/Source/Services/AssemblyTypeLister.Test.cs
new file mode 100644
index 0000000..a2fdb39
--- /dev/null
+++ b/Source/Services/AssemblyTypeLister.Test.cs
@@ -0,0 +1,138 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Services {
+
+ /// Unit Test for the cached assembly type lister
+ [TestFixture]
+ public class AssemblyTypeListerTest {
+
+ #region class TestAssemblyTypeLister
+
+ /// Test implementation of a cached assembly type lister
+ private class TestAssemblyTypeLister : AssemblyTypeLister {
+
+ /// Initializes a new test assembly type lister
+ /// Assemblies whose types will be listed
+ public TestAssemblyTypeLister(params Assembly[] assemblies) {
+ ReplaceAssemblyList(assemblies);
+ }
+
+ /// Replaces the list of assemblies whose types to list
+ /// Assemblies whose types will be listed
+ public void ReplaceAssemblyList(params Assembly[] assemblies) {
+ this.assemblies = assemblies;
+ }
+
+ /// Obtains a list of any assemblies whose types should be listed
+ /// A list of any assemblies whose types to list
+ protected override IEnumerable GetAssemblies() {
+ return this.assemblies;
+ }
+
+ /// Assemblies whose types the test assembly type lister lists
+ private Assembly[] assemblies;
+
+ }
+
+ #endregion // class TestAssemblyTypeLister
+
+ ///
+ /// Verifies that the assembly type list is generated correctly
+ ///
+ [Test]
+ public void TestAssemblyListGeneration() {
+ TestAssemblyTypeLister testLister = new TestAssemblyTypeLister(
+ typeof(AssemblyTypeListerTest).Assembly
+ );
+
+ Assert.That(
+ testLister.GetTypes(), Has.Member(typeof(AssemblyTypeListerTest))
+ );
+ }
+
+ ///
+ /// Verifies that the assembly type list is updated when list of assemblies
+ /// changes inbetween calls
+ ///
+ [Test]
+ public void TestAssemblyListReplacement() {
+ TestAssemblyTypeLister testLister = new TestAssemblyTypeLister(
+ typeof(Assembly).Assembly,
+ typeof(TestAttribute).Assembly
+ );
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(TestAttribute)).And.Not.Member(typeof(AssemblyTypeListerTest))
+ );
+
+ testLister.ReplaceAssemblyList(
+ typeof(Assembly).Assembly,
+ typeof(AssemblyTypeListerTest).Assembly
+ );
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(AssemblyTypeListerTest)).And.Not.Member(typeof(TestAttribute))
+ );
+ }
+
+ ///
+ /// Verifies that the assembly type list is updated when an assembly is removed
+ /// from the list inbetween calls
+ ///
+ [Test]
+ public void TestAssemblyListRemoval() {
+ TestAssemblyTypeLister testLister = new TestAssemblyTypeLister(
+ typeof(Assembly).Assembly,
+ typeof(TestAttribute).Assembly,
+ typeof(AssemblyTypeListerTest).Assembly
+ );
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(TestAttribute)).And.Member(typeof(AssemblyTypeListerTest))
+ );
+
+ testLister.ReplaceAssemblyList(
+ typeof(Assembly).Assembly,
+ typeof(AssemblyTypeListerTest).Assembly
+ );
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(AssemblyTypeListerTest)).And.Not.Member(typeof(TestAttribute))
+ );
+ }
+
+ }
+
+} // namespace Nuclex.Support.Services
+
+#endif // UNITTEST
diff --git a/Source/Services/AssemblyTypeLister.cs b/Source/Services/AssemblyTypeLister.cs
new file mode 100644
index 0000000..82ab8bd
--- /dev/null
+++ b/Source/Services/AssemblyTypeLister.cs
@@ -0,0 +1,143 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Nuclex.Support.Services {
+
+ /// Lists all types in a changing set of assemblies
+ public abstract class AssemblyTypeLister : ITypeLister {
+
+ #region class AssemblyTypes
+
+ /// Caches the list of types types for an assembly
+ private class AssemblyTypes {
+
+ /// Initializes a new cached assembly types list
+ /// Assembly the types are found in
+ /// Types defined in the assembly
+ public AssemblyTypes(Assembly assembly, Type[] types) {
+ this.Assembly = assembly;
+ this.Types = types;
+ }
+
+ /// Assembly the types are found in
+ public Assembly Assembly;
+ /// Types defined in the assembly
+ public Type[] Types;
+
+ }
+
+ #endregion // class AssemblyTypes
+
+ /// Initializes a new assembly type lister
+ public AssemblyTypeLister() {
+ this.assemblyTypes = new LinkedList();
+ }
+
+ /// Enumerates all types in the lister's assembly set
+ /// An enumerator over all types in the lister's assembly set
+ public IEnumerable GetTypes() {
+
+ // Make sure the assembly list is filled and up-to-date
+ if(this.assemblyTypes.Count == 0) {
+ enlistAssembliesFirstTime();
+ } else {
+ updateAssemblyList();
+ }
+
+ // Iterate over all types in all assemblies
+ LinkedListNode node = this.assemblyTypes.First;
+ while(node != null) {
+ Type[] types = node.Value.Types;
+ for(int index = 0; index < types.Length; ++index) {
+ yield return types[index];
+ }
+
+ node = node.Next;
+ }
+
+ }
+
+ /// Called when the assemblies set is queried for the first time
+ private void enlistAssembliesFirstTime() {
+ foreach(Assembly assembly in GetAssemblies()) {
+ this.assemblyTypes.AddLast(new AssemblyTypes(assembly, assembly.GetTypes()));
+ }
+ }
+
+ /// Called to update the assembly list if it has changed
+ private void updateAssemblyList() {
+ LinkedListNode node = this.assemblyTypes.First;
+
+ foreach(Assembly assembly in GetAssemblies()) {
+
+ // If we reached the end of the cache, this automatically becomes a new entry
+ if(node == null) {
+ this.assemblyTypes.AddLast(new AssemblyTypes(assembly, assembly.GetTypes()));
+ } else { // Otherwise, figure out whether the assembly list has changed
+
+ // Try to locate the cached entry for this assembly. If we have to skip entries,
+ // we know that an assembly might have been removed from the set.
+ LinkedListNode existingNode = node;
+ while(existingNode.Value.Assembly != assembly) {
+ existingNode = existingNode.Next;
+ if(existingNode == null) {
+ break;
+ }
+ }
+
+ // If this assembly wasn't found in the cache, add it in the same order
+ // it was returned by the enumerator.
+ if(existingNode == null) {
+ this.assemblyTypes.AddBefore(
+ node, new AssemblyTypes(assembly, assembly.GetTypes())
+ );
+ } else if(existingNode != node) { // Cached assemblies were skipped, reorder
+ this.assemblyTypes.Remove(existingNode);
+ this.assemblyTypes.AddBefore(node, existingNode);
+ } else { // Everything as expected
+ node = node.Next;
+ }
+ }
+
+ }
+
+ // Any nodes behind the last checked node contain cached type lists for assemblies
+ // that are no longer in the set, so these will be removed.
+ while(node != null) {
+ LinkedListNode nextNode = node.Next;
+ this.assemblyTypes.Remove(node);
+ node = nextNode;
+ }
+ }
+
+ /// Obtains a list of any assemblies whose types should be listed
+ /// A list of any assemblies whose types to list
+ protected abstract IEnumerable GetAssemblies();
+
+ /// Cached assembly type lists
+ private LinkedList assemblyTypes;
+
+ }
+
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/ITypeLister.cs b/Source/Services/ITypeLister.cs
new file mode 100644
index 0000000..e3fecee
--- /dev/null
+++ b/Source/Services/ITypeLister.cs
@@ -0,0 +1,42 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using Nuclex.Support.Plugins;
+
+namespace Nuclex.Support.Services {
+
+ ///
+ /// Provides a type list the service manager uses to locate components
+ ///
+ public interface ITypeLister {
+
+ ///
+ /// Returns an enumerable list of types that will be checked by the service manager
+ ///
+ /// An enumerable list of types for the service manager
+ IEnumerable GetTypes();
+
+ }
+
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/Instancing.cs b/Source/Services/Instancing.cs
index 8a40220..cc06de9 100644
--- a/Source/Services/Instancing.cs
+++ b/Source/Services/Instancing.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using Nuclex.Support.Plugins;
@@ -7,12 +27,19 @@ namespace Nuclex.Support.Services {
/// Modes in which services can be instantiated
public enum Instancing {
+
+ /// Disallow any service from being created for a contract
+ Never,
+
/// There will only be one service in the whole process
Singleton,
+
/// Each thread will be assigned its own service
InstancePerThread,
+
/// A new service will be created each time it is queried for
Factory
+
}
-} // namespace Nuclex.Support.DependencyInjection
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/PredefinedTypeLister.Test.cs b/Source/Services/PredefinedTypeLister.Test.cs
new file mode 100644
index 0000000..187d165
--- /dev/null
+++ b/Source/Services/PredefinedTypeLister.Test.cs
@@ -0,0 +1,103 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Services {
+
+ /// Unit Test for the predefined type lister
+ [TestFixture]
+ public class PredefinedTypeListerTest {
+
+ ///
+ /// Verifies that the type lister correctly takes over a list of types
+ /// supplied manually to the constructor
+ ///
+ [Test]
+ public void TestPredefinedTypesFromParams() {
+ ITypeLister testLister = new PredefinedTypeLister(
+ typeof(PredefinedTypeListerTest), typeof(TestAttribute)
+ );
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(PredefinedTypeListerTest)).And.Member(typeof(TestAttribute))
+ );
+ }
+
+ ///
+ /// Verifies that the type lister correctly takes over a list of types
+ /// supplied as an enumerable list to the constructor
+ ///
+ [Test]
+ public void TestPredefinedTypesFromEnumerable() {
+ IEnumerable types = typeof(PredefinedTypeListerTest).Assembly.GetTypes();
+ ITypeLister testLister = new PredefinedTypeLister(types);
+
+ Assert.That(
+ testLister.GetTypes(), Has.Member(typeof(PredefinedTypeListerTest))
+ );
+ }
+
+ ///
+ /// Verifies that types can be removed from the type lister
+ ///
+ [Test]
+ public void TestRemoveTypesFromLister() {
+ PredefinedTypeLister testLister = new PredefinedTypeLister(
+ typeof(PredefinedTypeListerTest).Assembly.GetTypes()
+ );
+
+ Assert.That(
+ testLister.GetTypes(), Has.Member(typeof(PredefinedTypeListerTest))
+ );
+ testLister.Types.Remove(typeof(PredefinedTypeListerTest));
+ Assert.That(
+ testLister.GetTypes(), Has.No.Member(typeof(PredefinedTypeListerTest))
+ );
+ }
+
+ ///
+ /// Verifies that types can be added to the type lister
+ ///
+ [Test]
+ public void TestAddTypesToLister() {
+ PredefinedTypeLister testLister = new PredefinedTypeLister();
+
+ Assert.That(
+ testLister.GetTypes(), Has.No.Member(typeof(TestAttribute))
+ );
+ testLister.Types.Add(typeof(TestAttribute));
+ Assert.That(
+ testLister.GetTypes(), Has.Member(typeof(TestAttribute))
+ );
+ }
+
+ }
+
+} // namespace Nuclex.Support.Services
+
+#endif // UNITTEST
diff --git a/Source/Services/PredefinedTypeLister.cs b/Source/Services/PredefinedTypeLister.cs
new file mode 100644
index 0000000..cc539f4
--- /dev/null
+++ b/Source/Services/PredefinedTypeLister.cs
@@ -0,0 +1,60 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Nuclex.Support.Services {
+
+ /// Type lister that returns a predefined list of types
+ public class PredefinedTypeLister : ITypeLister {
+
+ /// Initializes a new predefined type lister
+ /// Types the predefined type lister will list
+ public PredefinedTypeLister(params Type[] types) {
+ this.types = new List(types);
+ }
+
+ /// Initializes a new predefined type lister
+ /// Types the predefined type lister will list
+ public PredefinedTypeLister(IEnumerable types) {
+ this.types = new List(types);
+ }
+
+ ///
+ /// Returns an enumerable list of types that will be checked by the service manager
+ ///
+ /// An enumerable list of types for the service manager
+ public IEnumerable GetTypes() {
+ return this.types;
+ }
+
+ /// Predefined list of types the lister will list
+ public List Types {
+ get { return this.types; }
+ }
+
+ /// The predefined list of types
+ private List types;
+
+ }
+
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/ProgressTracking/IProgressTrackingService.cs b/Source/Services/ProgressTracking/IProgressCollectingService.cs
similarity index 79%
rename from Source/Services/ProgressTracking/IProgressTrackingService.cs
rename to Source/Services/ProgressTracking/IProgressCollectingService.cs
index da6702d..883617e 100644
--- a/Source/Services/ProgressTracking/IProgressTrackingService.cs
+++ b/Source/Services/ProgressTracking/IProgressCollectingService.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using Nuclex.Support.Tracking;
@@ -6,7 +26,7 @@ using Nuclex.Support.Tracking;
namespace Nuclex.Support.Services.ProgressTracking {
/// Allows application-wide tracking of progress
- interface IProgressTrackingService {
+ interface IProgressCollectingService {
/// Tracks the progress of the specified transaction
///
@@ -62,7 +82,7 @@ namespace Nuclex.Support.Services.ProgressTracking {
/// at all, dispite adding it to the progress tracking service).
///
void Untrack(Transaction transaction);
-
+
}
} // namespace Nuclex.Support.DependencyInjection.ProgressTracking
diff --git a/Source/Services/ProgressTracking/IProgressPublishingService.cs b/Source/Services/ProgressTracking/IProgressPublishingService.cs
index 1af810e..3d5969e 100644
--- a/Source/Services/ProgressTracking/IProgressPublishingService.cs
+++ b/Source/Services/ProgressTracking/IProgressPublishingService.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using Nuclex.Support.Tracking;
diff --git a/Source/Services/ProgressTracking/ITrackedProcess.cs b/Source/Services/ProgressTracking/ITrackedProcess.cs
index f26da31..1a49cc3 100644
--- a/Source/Services/ProgressTracking/ITrackedProcess.cs
+++ b/Source/Services/ProgressTracking/ITrackedProcess.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using Nuclex.Support.Tracking;
diff --git a/Source/Services/ProgressTracking/ProgressTrackingComponent.cs b/Source/Services/ProgressTracking/ProgressTrackingComponent.cs
index bc91fe9..f610a19 100644
--- a/Source/Services/ProgressTracking/ProgressTrackingComponent.cs
+++ b/Source/Services/ProgressTracking/ProgressTrackingComponent.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using Nuclex.Support.Tracking;
@@ -8,7 +28,7 @@ namespace Nuclex.Support.Services.ProgressTracking {
#if false
/// Tracks the progress of running background processes
public class ProgressTrackingComponent :
- IProgressTrackingService,
+ IProgressCollectingService,
IProgressPublishingService {
/// Fired when the overall progress changes
diff --git a/Source/Services/RepositoryTypeLister.Test.cs b/Source/Services/RepositoryTypeLister.Test.cs
new file mode 100644
index 0000000..aaa08a4
--- /dev/null
+++ b/Source/Services/RepositoryTypeLister.Test.cs
@@ -0,0 +1,63 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+#if UNITTEST
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Services {
+
+ /// Unit Test for the cached assembly repository type lister
+ [TestFixture]
+ public class RepositoryTypeListerTest {
+
+ ///
+ /// Tests whether the repository lister can cope with an empty repository
+ ///
+ [Test]
+ public void TestEmptyLister() {
+ RepositoryTypeLister testLister = new RepositoryTypeLister();
+
+ Assert.That(testLister.GetTypes(), Is.Empty);
+ }
+
+ ///
+ /// Tests whether the repository lister notices an updated repository
+ ///
+ [Test]
+ public void TestLateAdd() {
+ RepositoryTypeLister testLister = new RepositoryTypeLister();
+ testLister.Repository.AddAssembly(typeof(RepositoryTypeListerTest).Assembly);
+
+ Assert.That(
+ testLister.GetTypes(),
+ Has.Member(typeof(RepositoryTypeListerTest))
+ );
+ }
+
+ }
+
+} // namespace Nuclex.Support.Services
+
+#endif // UNITTEST
diff --git a/Source/Services/RepositoryTypeLister.cs b/Source/Services/RepositoryTypeLister.cs
new file mode 100644
index 0000000..826eb32
--- /dev/null
+++ b/Source/Services/RepositoryTypeLister.cs
@@ -0,0 +1,72 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+using Nuclex.Support.Plugins;
+
+namespace Nuclex.Support.Services {
+
+ ///
+ /// Lists the types of all assemblies contained in an assembly repository
+ ///
+ public class RepositoryTypeLister : AssemblyTypeLister {
+
+ ///
+ /// Initializes a new repository type lister using a new repository
+ ///
+ public RepositoryTypeLister() : this(new PluginRepository()) { }
+
+ ///
+ /// Initializes a new repository type lister using an existing repository
+ ///
+ ///
+ /// Repository containing the assemblies whose types will be listed
+ ///
+ public RepositoryTypeLister(PluginRepository repository) {
+ this.repository = repository;
+ }
+
+ ///
+ /// Returns an enumerable list of the assemblies in the repository
+ ///
+ /// An enumerable list of the assemblies in the repository
+ protected override IEnumerable GetAssemblies() {
+ return this.repository.LoadedAssemblies;
+ }
+
+ ///
+ /// The assembly repository containing the assemblies whose types the lister
+ /// operates on.
+ ///
+ public PluginRepository Repository {
+ get { return this.repository; }
+ }
+
+ ///
+ /// Repository containing the assemblies with the type lister's types
+ ///
+ private PluginRepository repository;
+
+ }
+
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/ServiceManager.For.cs b/Source/Services/ServiceManager.For.cs
index 3b7c003..a6f10c9 100644
--- a/Source/Services/ServiceManager.For.cs
+++ b/Source/Services/ServiceManager.For.cs
@@ -1,4 +1,24 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
using System.Text;
@@ -9,7 +29,6 @@ namespace Nuclex.Support.Services {
#region class ForContext
- // TODO: Rename to "On" to avoid confusion with concept of for loop?
/// Manages the context of the "For" modifier
public class ForContext {
@@ -52,7 +71,6 @@ namespace Nuclex.Support.Services {
#region class ForContext<>
- // TODO: Rename to "On" to avoid confusion with concept of for loop?
/// Manages the context of the "For" modifier
public class ForContext : ForContext {
@@ -93,4 +111,4 @@ namespace Nuclex.Support.Services {
}
#endif
-} // namespace Nuclex.Support.DependencyInjection
+} // namespace Nuclex.Support.Services
diff --git a/Source/Services/ServiceManager.Test.cs b/Source/Services/ServiceManager.Test.cs
new file mode 100644
index 0000000..b7a52cf
--- /dev/null
+++ b/Source/Services/ServiceManager.Test.cs
@@ -0,0 +1,191 @@
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
+using System.IO;
+
+#if UNITTEST
+
+using NUnit.Framework;
+
+namespace Nuclex.Support.Services {
+
+ /// Unit Test for the service manager class
+ [TestFixture]
+ public class ServiceManagerTest {
+
+ #region interface IHelloContract
+
+ /// A simple contract interface used for testing
+ public interface IHelloContract { }
+
+ #endregion // interface IHelloContract
+
+ #region interface IWorldContract
+
+ /// Another simple contract interface used for testing
+ public interface IWorldContract { }
+
+ #endregion // interface IWorldContract
+
+ #region interface IHaveNoImplementation
+
+ /// A contract interface that is not implementated anywhere
+ public interface IHaveNoImplementation { }
+
+ #endregion // interface IHaveNoImplementation
+
+ #region class HelloComponent
+
+ /// Test component that implements the hello contract
+ public class HelloComponent : IHelloContract { }
+
+ #endregion // class HelloComponent
+
+ #region class WorldComponent
+
+ ///
+ /// Test component that implements the world contract and requires
+ /// an implementation of the hello contract
+ ///
+ public class WorldComponent : IWorldContract, IHelloContract {
+ /// Initializes a new world component
+ ///
+ /// Array of hello contract implementations that will be used
+ ///
+ public WorldComponent(IHelloContract[] helloContracts) { }
+ }
+
+ #endregion // class WorldComponent
+
+ #region class IncompleteComponent
+
+ ///
+ /// Test component that requires an implementation of a contract that has
+ /// no implementation available
+ ///
+ public class IncompleteComponent : IWorldContract {
+ /// Initializes the component
+ ///
+ /// Implementation of the unimplemented interface (:P) to use
+ ///
+ public IncompleteComponent(IHaveNoImplementation noImplementation) { }
+ }
+
+ #endregion // class IncompleteComponent
+
+ #region class NeedHello
+
+ /// Component that needs an implementation of the hello contract
+ public class NeedHello : IWorldContract {
+ /// Initializes the component
+ ///
+ /// Implementation of the hello contract that will be used
+ ///
+ public NeedHello(IHelloContract helloContract) { }
+ }
+
+ #endregion // class NeedHello
+
+ #region class NeedWorld
+
+ /// Component that needs an implementation of the world contract
+ public class NeedWorld : IHelloContract {
+ /// Initializes the component
+ ///
+ /// Implementation of the world contract that will be used
+ ///
+ public NeedWorld(IWorldContract worldContract) { }
+ }
+
+ #endregion // class NeedWorld
+
+#if false
+ ///
+ /// Tests whether the GetComponents() method behaves correctly if it is used
+ /// without any assemblies loaded
+ ///
+ [Test]
+ public void TestGetComponentsWithoutAssembly() {
+ ServiceManager serviceManager = new ServiceManager();
+ Assert.That(serviceManager.GetComponents(), Is.Empty);
+ }
+
+ ///
+ /// Tests whether the GetComponents() method can locate a simple component
+ ///
+ [Test]
+ public void TestGetComponents() {
+ ServiceManager serviceManager = new ServiceManager();
+ serviceManager.Repository.AddAssembly(typeof(ServiceManagerTest).Assembly);
+
+ Assert.That(
+ serviceManager.GetComponents(),
+ Has.Member(typeof(HelloComponent)).And.Member(typeof(WorldComponent))
+ );
+ }
+
+ ///
+ /// Tests whether the GetComponents() method correctly determines which
+ /// components can have their dependencies completely provided.
+ ///
+ [Test]
+ public void TestFilteredGetComponents() {
+ ServiceManager serviceManager = new ServiceManager();
+ serviceManager.Repository.AddAssembly(typeof(ServiceManagerTest).Assembly);
+
+ Assert.That(
+ serviceManager.GetComponents(false),
+ Has.Member(typeof(WorldComponent)).And.Member(typeof(IncompleteComponent))
+ );
+ Assert.That(
+ serviceManager.GetComponents(true),
+ Has.Member(typeof(WorldComponent)).And.No.Member(typeof(IncompleteComponent))
+ );
+ }
+
+ ///
+ /// Tests whether the GetComponents() method can cope with two components
+ /// that have a circular dependency through their services.
+ ///
+ [Test]
+ public void TestCircularDependency() {
+
+ }
+
+ ///
+ /// Verifies that the right exception is thrown if the non-generic GetService()
+ /// is used on a value type
+ ///
+ [Test]
+ public void TestGetComponentOnValueType() {
+ ServiceManager serviceManager = new ServiceManager();
+ serviceManager.Repository.AddAssembly(typeof(int).Assembly);
+
+ Assert.Throws(
+ delegate() { serviceManager.GetService(typeof(int)); }
+ );
+ }
+#endif
+ }
+
+} // namespace Nuclex.Support.Services
+
+#endif // UNITTEST
diff --git a/Source/Services/ServiceManager.cs b/Source/Services/ServiceManager.cs
index a9baed0..d9161ba 100644
--- a/Source/Services/ServiceManager.cs
+++ b/Source/Services/ServiceManager.cs
@@ -1,12 +1,40 @@
-using System;
+#region CPL License
+/*
+Nuclex Framework
+Copyright (C) 2002-2009 Nuclex Development Labs
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the IBM Common Public License as
+published by the IBM Corporation; either version 1.0 of the
+License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+IBM Common Public License for more details.
+
+You should have received a copy of the IBM Common Public
+License along with this library
+*/
+#endregion
+
+using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Reflection;
+using System.Threading;
using Nuclex.Support.Plugins;
namespace Nuclex.Support.Services {
#if false
+
+ // Allow Dependency on Container
+ // public Foo(IServiceProvider serviceProvider)
+ // public Foo(IserviceLocator serviceLocator)
+ // public Foo(Container container)
+
///
/// Inversion of Control container that manages the services of an application
///
@@ -56,9 +84,110 @@ namespace Nuclex.Support.Services {
///
public partial class ServiceManager : IServiceProvider {
+ #region class Contract
+
+ /// Stores the settings for an individual contract
+ private class Contract {
+
+ ///
+ /// Factory by which instances of the contract implementation can be created
+ ///
+ public IAbstractFactory Factory;
+
+ /// How instances of the implementation are to be managed
+ public Instancing Instancing;
+
+ /// Single global instance of the contract implementation
+ ///
+ /// Used only if is set to Singleton
+ ///
+ public object SingletonInstance;
+
+ /// Thread-local instance of the contract implementation
+ ///
+ /// Used only if is set to InstancePerThread
+ ///
+ public object ThreadLocalInstance {
+ get {
+ initializeThreadLocalData();
+ return Thread.GetData(this.threadLocalDataSlot);
+ }
+ set {
+ initializeThreadLocalData();
+ Thread.SetData(this.threadLocalDataSlot, value);
+ }
+ }
+
+ /// Initializes the thread-local data slot
+ private void initializeThreadLocalData() {
+ if(this.threadLocalDataSlot == null) {
+ lock(this) {
+ if(this.threadLocalDataSlot == null) {
+ this.threadLocalDataSlot = Thread.AllocateDataSlot();
+ }
+ }
+ }
+ }
+
+ /// Arguments to be passed to the component constructor
+ private Dictionary arguments;
+
+ /// Data slot for thread local storage
+ ///
+ /// We're using an explicit data slot because the ThreadStaticAttribute class
+ /// can only be used on static fields and also because this class is not
+ /// supported by the .NET Compact Framework.
+ ///
+ private volatile LocalDataStoreSlot threadLocalDataSlot;
+
+ }
+
+ #endregion // class Contract
+
+#if !XBOX360
+
/// Initializes a new service manager
- public ServiceManager() {
- this.pluginRepository = new PluginRepository();
+ ///
+ /// This overload will automatically use a type lister that causes all types
+ /// in all loaded assemblies of the calling app domain to be considered
+ /// by the service manager for obtaining contract implementations.
+ ///
+ public ServiceManager() : this(new AppDomainTypeLister()) { }
+
+#endif // !XBOX360
+
+ /// Initializes a new service manager
+ ///
+ /// Type lister providing the types considered by the service manager for
+ /// obtaining contract implementations.
+ ///
+ public ServiceManager(ITypeLister typeLister) {
+ this.typeLister = typeLister;
+
+ resolveContractMethod = GetType().GetMethod(
+ "resolve", BindingFlags.NonPublic | BindingFlags.Instance
+ );
+ Debug.Assert(this.resolveContractMethod.IsGenericMethodDefinition);
+ }
+
+ ///
+ /// Returns all available implementations for the specified contract
+ ///
+ ///
+ /// A new enumerator for the available contract implementations
+ ///
+ public IEnumerable GetComponents() where ContractType : class {
+ Type contractType = typeof(ContractType);
+
+ foreach(Type checkedType in this.typeLister.GetTypes()) {
+ bool isImplementationOfContract =
+ (!checkedType.IsAbstract) &&
+ contractType.IsAssignableFrom(checkedType);
+
+ if(isImplementationOfContract) {
+ yield return checkedType;
+ }
+ }
}
///
@@ -71,31 +200,30 @@ namespace Nuclex.Support.Services {
///
/// A new enumerator for the available contract implementations
///
- IEnumerable GetImplementations(bool completeOnly)
+ public IEnumerable GetComponents(bool completeOnly)
where ContractType : class {
- Type contractType = typeof(ContractType);
+ if(completeOnly) {
+ return filterCompleteComponents(GetComponents());
+ } else {
+ return GetComponents();
+ }
+ }
- Assembly[] loadedAssemblies = this.pluginRepository.LoadedAssemblies.ToArray();
- for(int index = 0; index < loadedAssemblies.Length; ++index) {
- Type[] assemblyTypes = loadedAssemblies[index].GetTypes();
-
- for(int typeIndex = 0; typeIndex < assemblyTypes.Length; ++typeIndex) {
- Type checkedType = assemblyTypes[typeIndex];
- if(contractType.IsAssignableFrom(checkedType)) {
-
- }
- }
+ ///
+ /// Filters a list of components so only components whose dependencies can be
+ /// completely provided are enumerated
+ ///
+ /// Enumerable type list that will be filtered
+ ///
+ /// Only those components whose dependencies can be completely provided
+ ///
+ private IEnumerable filterCompleteComponents(IEnumerable types) {
+ foreach(Type type in types) {
+ yield return type;
}
- yield return null;
+ yield break;
}
-
- private struct CachedContractLookUp {
- public Type[] ValidComponents;
- public int Version;
- }
- private Dictionary cachedContracts;
- private int version;
///
/// Allows the adjustment of the container's behavior in regard to
@@ -127,11 +255,11 @@ namespace Nuclex.Support.Services {
return new ForContext(this, contractType);
}
- // Allow Dependency on Container
- // public Foo(IServiceProvider serviceProvider)
- // public Foo(IserviceLocator serviceLocator)
- // public Foo(Container container)
-
+ /// Retrieves the service of the specified type
+ ///
+ /// Contract for which the service will be retrieved
+ ///
+ /// The service for the specified contract
public ContractType GetService() where ContractType : class {
throw new NotImplementedException();
}
@@ -141,16 +269,44 @@ namespace Nuclex.Support.Services {
/// Contract for which the service will be retrieved
///
/// The service for the specified contract
- object IServiceProvider.GetService(Type contractType) {
- throw new NotImplementedException();
+ public object GetService(Type contractType) {
+ MethodInfo methodInstance = this.resolveContractMethod.MakeGenericMethod(
+ new Type[] { contractType }
+ );
+ return methodInstance.Invoke(this, null);
}
///
- /// Contains all assemblies partaking in the dependency injection scheme
+ /// Resolves all dependencies required to create a service for a contract
///
- private PluginRepository pluginRepository;
+ ///
+ /// Type of contract for which to resolve the implementation
+ ///
+ /// The settings for the contract including a valid factory
+ private Contract resolveContract() where ContractType : class {
+ throw new NotImplementedException();
+ }
+
+ private Contract resolveContract(Type contractType) {
+ Contract contract;
+ if(this.contracts.TryGetValue(contractType, out contract)) {
+ return contract;
+ }
+
+
+
+ throw new NotImplementedException();
+ }
+
+ /// MethodInfo for the resolve() method of this instance
+ private MethodInfo resolveContractMethod;
+ /// Lists all types partaking in the dependency injection
+ private ITypeLister typeLister;
+ /// Dictionary with settings for each individual contract
+ private Dictionary contracts;
}
+
#endif
-} // namespace Nuclex.Support.DependencyInjection
+} // namespace Nuclex.Support.Services