Moves services directory into Nuclex.Support.Plugins project
git-svn-id: file:///srv/devel/repo-conversion/nusu@276 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
c9b20cd2cd
commit
92733d147b
|
@ -1,77 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Unit Test for the cached app domain type lister</summary>
|
||||
[TestFixture]
|
||||
public class AppDomainTypeListerTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the assembly type list is generated correctly for
|
||||
/// the default constructor (using the calling app domain)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDefaultConstructur() {
|
||||
AppDomainTypeLister testLister = new AppDomainTypeLister();
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(),
|
||||
Has.Member(typeof(AppDomainTypeListerTest)).And.Member(typeof(Assembly))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the assembly type list is generated correctly for
|
||||
/// the full constructor
|
||||
/// </summary>
|
||||
[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 // ENABLE_SERVICEMANAGER
|
||||
|
||||
#endif // UNITTEST
|
|
@ -1,63 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
#if WINDOWS
|
||||
|
||||
/// <summary>Lists the types of all assemblies in an application domain</summary>
|
||||
public class AppDomainTypeLister : MultiAssemblyTypeLister {
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new application domain type lister using the application domain
|
||||
/// of the calling method
|
||||
/// </summary>
|
||||
public AppDomainTypeLister() : this(AppDomain.CurrentDomain) { }
|
||||
|
||||
/// <summary>Initializes a new application domain type lister</summary>
|
||||
/// <param name="appDomain">Application domain whose types will be listed</param>
|
||||
public AppDomainTypeLister(AppDomain appDomain) {
|
||||
this.appDomain = appDomain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains an enumerable list of all assemblies in the application domain
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of the assemblies in the application domain</returns>
|
||||
protected override IEnumerable<Assembly> GetAssemblies() {
|
||||
return this.appDomain.GetAssemblies();
|
||||
}
|
||||
|
||||
/// <summary>Application domain whose types the lister works on</summary>
|
||||
private AppDomain appDomain;
|
||||
|
||||
}
|
||||
|
||||
#endif // WINDOWS
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,107 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Unit Test for the predefined type lister</summary>
|
||||
[TestFixture]
|
||||
public class ExplicitTypeListerTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the type lister correctly takes over a list of types
|
||||
/// supplied manually to the constructor
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPredefinedTypesFromParams() {
|
||||
ITypeLister testLister = new ExplicitTypeLister(
|
||||
typeof(ExplicitTypeListerTest), typeof(TestAttribute)
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(),
|
||||
Has.Member(typeof(ExplicitTypeListerTest)).And.Member(typeof(TestAttribute))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the type lister correctly takes over a list of types
|
||||
/// supplied as an enumerable list to the constructor
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPredefinedTypesFromEnumerable() {
|
||||
IEnumerable<Type> types = typeof(ExplicitTypeListerTest).Assembly.GetTypes();
|
||||
ITypeLister testLister = new ExplicitTypeLister(types);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(), Has.Member(typeof(ExplicitTypeListerTest))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that types can be removed from the type lister
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveTypesFromLister() {
|
||||
ExplicitTypeLister testLister = new ExplicitTypeLister(
|
||||
typeof(ExplicitTypeListerTest).Assembly.GetTypes()
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(), Has.Member(typeof(ExplicitTypeListerTest))
|
||||
);
|
||||
testLister.Types.Remove(typeof(ExplicitTypeListerTest));
|
||||
Assert.That(
|
||||
testLister.GetTypes(), Has.No.Member(typeof(ExplicitTypeListerTest))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that types can be added to the type lister
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddTypesToLister() {
|
||||
ExplicitTypeLister testLister = new ExplicitTypeLister();
|
||||
|
||||
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 // ENABLE_SERVICEMANAGER
|
||||
|
||||
#endif // UNITTEST
|
|
@ -1,64 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Type lister that returns a predefined list of types</summary>
|
||||
public class ExplicitTypeLister : ITypeLister {
|
||||
|
||||
/// <summary>Initializes a new predefined type lister</summary>
|
||||
/// <param name="types">Types the predefined type lister will list</param>
|
||||
public ExplicitTypeLister(params Type[] types) {
|
||||
this.types = new List<Type>(types);
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new predefined type lister</summary>
|
||||
/// <param name="types">Types the predefined type lister will list</param>
|
||||
public ExplicitTypeLister(IEnumerable<Type> types) {
|
||||
this.types = new List<Type>(types);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerable list of types that will be checked by the service manager
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of types for the service manager</returns>
|
||||
public IEnumerable<Type> GetTypes() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
/// <summary>Predefined list of types the lister will list</summary>
|
||||
public List<Type> Types {
|
||||
get { return this.types; }
|
||||
}
|
||||
|
||||
/// <summary>The predefined list of types</summary>
|
||||
private List<Type> types;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,46 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>
|
||||
/// Provides a type list the service manager uses to locate components
|
||||
/// </summary>
|
||||
public interface ITypeLister {
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerable list of types that will be checked by the service manager
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of types for the service manager</returns>
|
||||
IEnumerable<Type> GetTypes();
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,49 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Modes in which services can be instantiated</summary>
|
||||
public enum Instancing {
|
||||
|
||||
/// <summary>Disallow any service from being created for a contract</summary>
|
||||
Never,
|
||||
|
||||
/// <summary>There will only be one service in the whole process</summary>
|
||||
Singleton,
|
||||
|
||||
/// <summary>Each thread will be assigned its own service</summary>
|
||||
InstancePerThread,
|
||||
|
||||
/// <summary>A new service will be created each time it is queried for</summary>
|
||||
Factory
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,143 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Unit Test for the cached assembly type lister</summary>
|
||||
[TestFixture]
|
||||
public class MultiAssemblyTypeListerTest {
|
||||
|
||||
#region class TestAssemblyTypeLister
|
||||
|
||||
/// <summary>Test implementation of a cached assembly type lister</summary>
|
||||
private class TestAssemblyTypeLister : MultiAssemblyTypeLister {
|
||||
|
||||
/// <summary>Initializes a new test assembly type lister</summary>
|
||||
/// <param name="assemblies">Assemblies whose types will be listed</param>
|
||||
public TestAssemblyTypeLister(params Assembly[] assemblies) {
|
||||
ReplaceAssemblyList(assemblies);
|
||||
}
|
||||
|
||||
/// <summary>Replaces the list of assemblies whose types to list</summary>
|
||||
/// <param name="assemblies">Assemblies whose types will be listed</param>
|
||||
public void ReplaceAssemblyList(params Assembly[] assemblies) {
|
||||
this.assemblies = assemblies;
|
||||
}
|
||||
|
||||
/// <summary>Obtains a list of any assemblies whose types should be listed</summary>
|
||||
/// <returns>A list of any assemblies whose types to list</returns>
|
||||
protected override IEnumerable<Assembly> GetAssemblies() {
|
||||
return this.assemblies;
|
||||
}
|
||||
|
||||
/// <summary>Assemblies whose types the test assembly type lister lists</summary>
|
||||
private Assembly[] assemblies;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestAssemblyTypeLister
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the assembly type list is generated correctly
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAssemblyListGeneration() {
|
||||
TestAssemblyTypeLister testLister = new TestAssemblyTypeLister(
|
||||
typeof(MultiAssemblyTypeListerTest).Assembly
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(), Has.Member(typeof(MultiAssemblyTypeListerTest))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the assembly type list is updated when list of assemblies
|
||||
/// changes inbetween calls
|
||||
/// </summary>
|
||||
[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(MultiAssemblyTypeListerTest))
|
||||
);
|
||||
|
||||
testLister.ReplaceAssemblyList(
|
||||
typeof(Assembly).Assembly,
|
||||
typeof(MultiAssemblyTypeListerTest).Assembly
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(),
|
||||
Has.Member(typeof(MultiAssemblyTypeListerTest)).And.Not.Member(typeof(TestAttribute))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the assembly type list is updated when an assembly is removed
|
||||
/// from the list inbetween calls
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAssemblyListRemoval() {
|
||||
TestAssemblyTypeLister testLister = new TestAssemblyTypeLister(
|
||||
typeof(Assembly).Assembly,
|
||||
typeof(TestAttribute).Assembly,
|
||||
typeof(MultiAssemblyTypeListerTest).Assembly
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(),
|
||||
Has.Member(typeof(TestAttribute)).And.Member(typeof(MultiAssemblyTypeListerTest))
|
||||
);
|
||||
|
||||
testLister.ReplaceAssemblyList(
|
||||
typeof(Assembly).Assembly,
|
||||
typeof(MultiAssemblyTypeListerTest).Assembly
|
||||
);
|
||||
|
||||
Assert.That(
|
||||
testLister.GetTypes(),
|
||||
Has.Member(typeof(MultiAssemblyTypeListerTest)).And.Not.Member(typeof(TestAttribute))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
||||
|
||||
#endif // UNITTEST
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Lists all types in a changing set of assemblies</summary>
|
||||
public abstract class MultiAssemblyTypeLister : ITypeLister {
|
||||
|
||||
#region class AssemblyTypes
|
||||
|
||||
/// <summary>Caches the list of types types for an assembly</summary>
|
||||
private class AssemblyTypes {
|
||||
|
||||
/// <summary>Initializes a new cached assembly types list</summary>
|
||||
/// <param name="assembly">Assembly the types are found in</param>
|
||||
/// <param name="types">Types defined in the assembly</param>
|
||||
public AssemblyTypes(Assembly assembly, Type[] types) {
|
||||
this.Assembly = assembly;
|
||||
this.Types = types;
|
||||
}
|
||||
|
||||
/// <summary>Assembly the types are found in</summary>
|
||||
public Assembly Assembly;
|
||||
/// <summary>Types defined in the assembly</summary>
|
||||
public Type[] Types;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class AssemblyTypes
|
||||
|
||||
/// <summary>Initializes a new assembly type lister</summary>
|
||||
public MultiAssemblyTypeLister() {
|
||||
this.assemblyTypes = new LinkedList<AssemblyTypes>();
|
||||
}
|
||||
|
||||
/// <summary>Enumerates all types in the lister's assembly set</summary>
|
||||
/// <returns>An enumerator over all types in the lister's assembly set</returns>
|
||||
public IEnumerable<Type> 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<AssemblyTypes> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Called when the assemblies set is queried for the first time</summary>
|
||||
private void enlistAssembliesFirstTime() {
|
||||
foreach(Assembly assembly in GetAssemblies()) {
|
||||
this.assemblyTypes.AddLast(new AssemblyTypes(assembly, assembly.GetTypes()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Called to update the assembly list if it has changed</summary>
|
||||
private void updateAssemblyList() {
|
||||
LinkedListNode<AssemblyTypes> 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. This will be
|
||||
// handled by moved all matched assemblies to the beginning, so that when we
|
||||
// finish, the assemblies after the last checked one automatically become those
|
||||
// which are no longer in the set.
|
||||
LinkedListNode<AssemblyTypes> existingNode = node;
|
||||
while(existingNode.Value.Assembly != assembly) {
|
||||
existingNode = existingNode.Next;
|
||||
if(existingNode == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this assembly not yet in the cache?
|
||||
if(existingNode == null) {
|
||||
|
||||
// If this assembly wasn't found in the cache, add it in the same order
|
||||
// it was returned by the enumerator. This will improve efficiency later
|
||||
// since the update algorithm is designed to perform optimally if the order
|
||||
// remains the same between calls.
|
||||
this.assemblyTypes.AddBefore(
|
||||
node, new AssemblyTypes(assembly, assembly.GetTypes())
|
||||
);
|
||||
|
||||
} else if(existingNode != node) { // Did we skip other cached assemblies?
|
||||
|
||||
// If other cached assemblies had to be skipped, this indicates that
|
||||
// the set of assemblies has changed. Move the list nodes to the same order
|
||||
// in which the assemblies are returned by the enumerator. Any cached
|
||||
// assemblies that have been completely removed from the set will therefore
|
||||
// end up at the bottom of the list after the update has completed.
|
||||
this.assemblyTypes.Remove(existingNode);
|
||||
this.assemblyTypes.AddBefore(node, existingNode);
|
||||
|
||||
} else { // Assembly was found in the expected place
|
||||
|
||||
// If the assembly was found in the same place as it was found during
|
||||
// the last check, the assembly list is unchanged at this entry.
|
||||
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<AssemblyTypes> nextNode = node.Next;
|
||||
this.assemblyTypes.Remove(node);
|
||||
node = nextNode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Obtains a list of any assemblies whose types should be listed</summary>
|
||||
/// <returns>A list of any assemblies whose types to list</returns>
|
||||
protected abstract IEnumerable<Assembly> GetAssemblies();
|
||||
|
||||
/// <summary>Cached assembly type lists</summary>
|
||||
private LinkedList<AssemblyTypes> assemblyTypes;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,92 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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 ENABLE_SERVICEMANAGER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Nuclex.Support.Tracking;
|
||||
|
||||
namespace Nuclex.Support.Services.ProgressTracking {
|
||||
|
||||
/// <summary>Allows application-wide tracking of progress</summary>
|
||||
interface IProgressCollectingService {
|
||||
|
||||
/// <summary>Tracks the progress of the specified transaction</summary>
|
||||
/// <param name="transaction">
|
||||
/// Transaction whose progress will be tracked
|
||||
/// </param>
|
||||
/// <param name="processIdentifier">
|
||||
/// Identifier unique to the tracked background process. Can be null.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Using the process identifier allows you to track the progress of multiple
|
||||
/// transactions that are working independently of each other. This could,
|
||||
/// for example, result in multiple progress bars being displayed in a GUI.
|
||||
/// The global progress always is a combination of all transactions tracked
|
||||
/// by the service.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A good analogy for this might be a download manager which uses several
|
||||
/// threads to download multiple sections of a file at the same time. You
|
||||
/// want a progress bar per file, but not one for each downloading thread.
|
||||
/// Specifying the name object as a process identifer, all transactions
|
||||
/// belonging to the same file would be merged into a single progress source.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The process identifier can be a string or any object. Note however that
|
||||
/// as common practice, this object's ToString() method should return
|
||||
/// something reasonable, like "Downloading xy.txt". Localization can be
|
||||
/// achieved by implementing an interface (eg. ILocalizableToString) which
|
||||
/// provides a string and some parameters - or you could return the already
|
||||
/// translated versions of the string if you prefer to have localized versions
|
||||
/// of internal assemblies.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
void Track(Transaction transaction, object processIdentifier);
|
||||
|
||||
/// <summary>Tracks the progress of the specified transaction</summary>
|
||||
/// <param name="transaction">
|
||||
/// Transaction whose progress will be tracked
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Tracks the transaction as if it was added with the process identifier
|
||||
/// set to null.
|
||||
/// </remarks>
|
||||
void Track(Transaction transaction);
|
||||
|
||||
/// <summary>Stops tracking the specified transaction</summary>
|
||||
/// <param name="transaction">Transaction that will no longer be tracked</param>
|
||||
/// <remarks>
|
||||
/// Untracking a transaction is optional. The service will automatically
|
||||
/// remove finished transactions from its list of tracked transactions. Calling
|
||||
/// this method is only required if you drop a transaction in a way that
|
||||
/// prevents its AsyncEnded event from being fired (eg. by not executing it
|
||||
/// at all, dispite adding it to the progress tracking service).
|
||||
/// </remarks>
|
||||
void Untrack(Transaction transaction);
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.DependencyInjection.ProgressTracking
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,58 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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 ENABLE_SERVICEMANAGER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Nuclex.Support.Tracking;
|
||||
|
||||
namespace Nuclex.Support.Services.ProgressTracking {
|
||||
|
||||
/// <summary>Reports the progress of tracked background processes</summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This service is intended for the consumer of progress reports. It will notify
|
||||
/// subscribers when background processes start, when progress is achieved and
|
||||
/// when they finish.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Usually, this interface, together with the IProgressTrackingService interface,
|
||||
/// is provided by a single service component that tracks the progress of
|
||||
/// transactions taking place asynchronously and reports it back this way.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
interface IProgressPublishingService {
|
||||
|
||||
/// <summary>Fired when the overall progress changes</summary>
|
||||
event EventHandler<ProgressReportEventArgs> ProgressChanged;
|
||||
|
||||
/// <summary>The overall progress of all tracked background processes</summary>
|
||||
float TotalProgress { get; }
|
||||
|
||||
/// <summary>Currently active background processes</summary>
|
||||
IEnumerable<ITrackedProcess> TrackedProcesses { get; }
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.DependencyInjection.ProgressTracking
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,53 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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 ENABLE_SERVICEMANAGER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Nuclex.Support.Tracking;
|
||||
|
||||
namespace Nuclex.Support.Services.ProgressTracking {
|
||||
|
||||
/// <summary>Process whose progress is being tracked</summary>
|
||||
public interface ITrackedProcess {
|
||||
|
||||
/// <summary>Fired whenever the progress of the process changes</summary>
|
||||
event EventHandler<ProgressReportEventArgs> ProgressChanged;
|
||||
|
||||
/// <summary>Unique identifier of the overall process</summary>
|
||||
/// <remarks>
|
||||
/// As a convention, using this object's ToString() method should return
|
||||
/// something usable, either a string that can be displayed in the user
|
||||
/// interface or, depending on your architecture, the object could
|
||||
/// implement certain interfaces that allow a localized version of
|
||||
/// the string to be created.
|
||||
/// </remarks>
|
||||
object ProcessIdentifier { get; }
|
||||
|
||||
/// <summary>Progress that process has achieved so far</summary>
|
||||
float CurrentProgress { get; }
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.DependencyInjection.ProgressTracking
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,78 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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 ENABLE_SERVICEMANAGER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Nuclex.Support.Tracking;
|
||||
|
||||
namespace Nuclex.Support.Services.ProgressTracking {
|
||||
|
||||
/// <summary>Tracks the progress of running background processes</summary>
|
||||
public class ProgressTrackingComponent :
|
||||
IProgressCollectingService,
|
||||
IProgressPublishingService {
|
||||
|
||||
/// <summary>Fired when the overall progress changes</summary>
|
||||
public event EventHandler<ProgressReportEventArgs> ProgressChanged;
|
||||
|
||||
/// <summary>Initializes a new progress tracking component</summary>
|
||||
public ProgressTrackingComponent() {
|
||||
}
|
||||
|
||||
/// <summary>Tracks the progress of the specified transaction</summary>
|
||||
/// <param name="transaction">
|
||||
/// Transaction whose progress will be tracked
|
||||
/// </param>
|
||||
/// <param name="processIdentifier">
|
||||
/// Identifier unique to the tracked background process. Can be null.
|
||||
/// </param>
|
||||
public void Track(Transaction transaction, object processIdentifier) {
|
||||
}
|
||||
|
||||
/// <summary>Tracks the progress of the specified transaction</summary>
|
||||
/// <param name="transaction">
|
||||
/// Transaction whose progress will be tracked
|
||||
/// </param>
|
||||
public void Track(Transaction transaction) {
|
||||
}
|
||||
|
||||
/// <summary>Stops tracking the specified transaction</summary>
|
||||
/// <param name="transaction">Transaction that will no longer be tracked</param>
|
||||
public void Untrack(Transaction transaction) {
|
||||
}
|
||||
|
||||
/// <summary>The overall progress of all tracked background processes</summary>
|
||||
public float TotalProgress {
|
||||
get { return 0.0f; }
|
||||
}
|
||||
|
||||
/// <summary>Currently active background processes</summary>
|
||||
public IEnumerable<ITrackedProcess> TrackedProcesses {
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services.ProgressTracking
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,67 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Unit Test for the cached assembly repository type lister</summary>
|
||||
[TestFixture]
|
||||
public class RepositoryTypeListerTest {
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the repository lister can cope with an empty repository
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEmptyLister() {
|
||||
RepositoryTypeLister testLister = new RepositoryTypeLister();
|
||||
|
||||
Assert.That(testLister.GetTypes(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the repository lister notices an updated repository
|
||||
/// </summary>
|
||||
[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 // ENABLE_SERVICEMANAGER
|
||||
|
||||
#endif // UNITTEST
|
|
@ -1,76 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>
|
||||
/// Lists the types of all assemblies contained in an assembly repository
|
||||
/// </summary>
|
||||
public class RepositoryTypeLister : MultiAssemblyTypeLister {
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new repository type lister using a new repository
|
||||
/// </summary>
|
||||
public RepositoryTypeLister() : this(new PluginRepository()) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new repository type lister using an existing repository
|
||||
/// </summary>
|
||||
/// <param name="repository">
|
||||
/// Repository containing the assemblies whose types will be listed
|
||||
/// </param>
|
||||
public RepositoryTypeLister(PluginRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerable list of the assemblies in the repository
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of the assemblies in the repository</returns>
|
||||
protected override IEnumerable<Assembly> GetAssemblies() {
|
||||
return this.repository.LoadedAssemblies;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The assembly repository containing the assemblies whose types the lister
|
||||
/// operates on.
|
||||
/// </summary>
|
||||
public PluginRepository Repository {
|
||||
get { return this.repository; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repository containing the assemblies with the type lister's types
|
||||
/// </summary>
|
||||
private PluginRepository repository;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,53 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
partial class ServiceManager {
|
||||
|
||||
#region class Analyzer
|
||||
|
||||
/// <summary>Analyzes Component dependencies</summary>
|
||||
private static class Analyzer {
|
||||
|
||||
|
||||
|
||||
public static KeyValuePair<string, Type>[] GetRequirements(ConstructorInfo constructor) {
|
||||
ParameterInfo[] parameters = constructor.GetParameters();
|
||||
//parameters[0].IsOptional
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion // class Analyzer
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,116 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
partial class ServiceManager {
|
||||
|
||||
#region class ForContext
|
||||
|
||||
/// <summary>Manages the context of the "For" modifier</summary>
|
||||
public class ForContext {
|
||||
|
||||
/// <summary>Initializes a new "For" context of the service manager</summary>
|
||||
/// <param name="serviceManager">Service manager the context operates on</param>
|
||||
/// <param name="contractType">Contract that is being modified</param>
|
||||
internal ForContext(ServiceManager serviceManager, Type contractType) {
|
||||
this.serviceManager = serviceManager;
|
||||
this.contractType = contractType;
|
||||
}
|
||||
|
||||
/// <summary>Uses the specified implementation for the contract</summary>
|
||||
/// <param name="contractImplementation">
|
||||
/// Implementation that will be used for the contract
|
||||
/// </param>
|
||||
public void Use(object contractImplementation) { }
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided object as a prototype for the contract implementation
|
||||
/// </summary>
|
||||
/// <param name="contractImplementationPrototype">
|
||||
/// Contract implementation that will be used as a prototype
|
||||
/// </param>
|
||||
public void UsePrototype(object contractImplementationPrototype) { }
|
||||
|
||||
/// <summary>Selects the default implementation to use for the contract</summary>
|
||||
/// <param name="implementationType">
|
||||
/// Implementation that will be used as the default for the contract
|
||||
/// </param>
|
||||
public void UseDefault(Type implementationType) { }
|
||||
|
||||
/// <summary>Service manager the "For" context operates on</summary>
|
||||
protected ServiceManager serviceManager;
|
||||
/// <summary>Contract that is being modified</summary>
|
||||
protected Type contractType;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class ForContext
|
||||
|
||||
#region class ForContext<>
|
||||
|
||||
/// <summary>Manages the context of the "For" modifier</summary>
|
||||
public class ForContext<ContractType> : ForContext {
|
||||
|
||||
/// <summary>Initializes a new "For" context of the service manager</summary>
|
||||
/// <param name="serviceManager">Service manager the context operates on</param>
|
||||
internal ForContext(ServiceManager serviceManager) :
|
||||
base(serviceManager, typeof(ContractType)) { }
|
||||
|
||||
/// <summary>Uses the specified implementation for the contract</summary>
|
||||
/// <param name="implementation">
|
||||
/// Implementation that will be used for the contract
|
||||
/// </param>
|
||||
public void Use(ContractType implementation) { }
|
||||
|
||||
/// <summary>
|
||||
/// Uses the provided object as a prototype for the contract implementation
|
||||
/// </summary>
|
||||
/// <typeparam name="PrototypeType">
|
||||
/// Type of the implementation that will be used as a prototype
|
||||
/// </typeparam>
|
||||
/// <param name="contractImplementationPrototype">
|
||||
/// Contract implementation that will be used as a prototype
|
||||
/// </param>
|
||||
public void UsePrototype<PrototypeType>(PrototypeType contractImplementationPrototype)
|
||||
where PrototypeType : ContractType, ICloneable { }
|
||||
|
||||
/// <summary>Selects the default implementation to use for the contract</summary>
|
||||
/// <typeparam name="ImplementationType">
|
||||
/// Implementation that will be used as the default for the contract
|
||||
/// </typeparam>
|
||||
public void UseDefault<ImplementationType>()
|
||||
where ImplementationType : ContractType { }
|
||||
|
||||
}
|
||||
|
||||
#endregion // class ForContext<>
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
|
@ -1,199 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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 Nuclex.Support.Plugins;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
/// <summary>Unit Test for the service manager class</summary>
|
||||
[TestFixture]
|
||||
public class ServiceManagerTest {
|
||||
|
||||
#region interface IHelloContract
|
||||
|
||||
/// <summary>A simple contract interface used for testing</summary>
|
||||
public interface IHelloContract { }
|
||||
|
||||
#endregion // interface IHelloContract
|
||||
|
||||
#region interface IWorldContract
|
||||
|
||||
/// <summary>Another simple contract interface used for testing</summary>
|
||||
public interface IWorldContract { }
|
||||
|
||||
#endregion // interface IWorldContract
|
||||
|
||||
#region interface IHaveNoImplementation
|
||||
|
||||
/// <summary>A contract interface that is not implementated anywhere</summary>
|
||||
public interface IHaveNoImplementation { }
|
||||
|
||||
#endregion // interface IHaveNoImplementation
|
||||
|
||||
#region class HelloComponent
|
||||
|
||||
/// <summary>Test component that implements the hello contract</summary>
|
||||
public class HelloComponent : IHelloContract { }
|
||||
|
||||
#endregion // class HelloComponent
|
||||
|
||||
#region class WorldComponent
|
||||
|
||||
/// <summary>
|
||||
/// Test component that implements the world contract and requires
|
||||
/// an implementation of the hello contract
|
||||
/// </summary>
|
||||
public class WorldComponent : IWorldContract, IHelloContract {
|
||||
/// <summary>Initializes a new world component</summary>
|
||||
/// <param name="helloContracts">
|
||||
/// Array of hello contract implementations that will be used
|
||||
/// </param>
|
||||
public WorldComponent(IHelloContract[] helloContracts) { }
|
||||
}
|
||||
|
||||
#endregion // class WorldComponent
|
||||
|
||||
#region class IncompleteComponent
|
||||
|
||||
/// <summary>
|
||||
/// Test component that requires an implementation of a contract that has
|
||||
/// no implementation available
|
||||
/// </summary>
|
||||
public class IncompleteComponent : IWorldContract {
|
||||
/// <summary>Initializes the component</summary>
|
||||
/// <param name="noImplementation">
|
||||
/// Implementation of the unimplemented interface (:P) to use
|
||||
/// </param>
|
||||
public IncompleteComponent(IHaveNoImplementation noImplementation) { }
|
||||
}
|
||||
|
||||
#endregion // class IncompleteComponent
|
||||
|
||||
#region class NeedHello
|
||||
|
||||
/// <summary>Component that needs an implementation of the hello contract</summary>
|
||||
public class NeedHello : IWorldContract {
|
||||
/// <summary>Initializes the component</summary>
|
||||
/// <param name="helloContract">
|
||||
/// Implementation of the hello contract that will be used
|
||||
/// </param>
|
||||
public NeedHello(IHelloContract helloContract) { }
|
||||
}
|
||||
|
||||
#endregion // class NeedHello
|
||||
|
||||
#region class NeedWorld
|
||||
|
||||
/// <summary>Component that needs an implementation of the world contract</summary>
|
||||
public class NeedWorld : IHelloContract {
|
||||
/// <summary>Initializes the component</summary>
|
||||
/// <param name="worldContract">
|
||||
/// Implementation of the world contract that will be used
|
||||
/// </param>
|
||||
public NeedWorld(IWorldContract worldContract) { }
|
||||
}
|
||||
|
||||
#endregion // class NeedWorld
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the GetComponents() method behaves correctly if it is used
|
||||
/// without any assemblies loaded
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetComponentsWithoutAssembly() {
|
||||
ServiceManager serviceManager = new ServiceManager(new PredefinedTypeLister());
|
||||
Assert.That(serviceManager.GetComponents<IDisposable>(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the GetComponents() method can locate a simple component
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetComponents() {
|
||||
RepositoryTypeLister typeLister = new RepositoryTypeLister();
|
||||
ServiceManager serviceManager = new ServiceManager(typeLister);
|
||||
typeLister.Repository.AddAssembly(typeof(ServiceManagerTest).Assembly);
|
||||
|
||||
Assert.That(
|
||||
serviceManager.GetComponents<IHelloContract>(),
|
||||
Has.Member(typeof(HelloComponent)).And.Member(typeof(WorldComponent))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the GetComponents() method correctly determines which
|
||||
/// components can have their dependencies completely provided.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFilteredGetComponents() {
|
||||
RepositoryTypeLister typeLister = new RepositoryTypeLister();
|
||||
ServiceManager serviceManager = new ServiceManager(typeLister);
|
||||
typeLister.Repository.AddAssembly(typeof(ServiceManagerTest).Assembly);
|
||||
|
||||
Assert.That(
|
||||
serviceManager.GetComponents<IWorldContract>(false),
|
||||
Has.Member(typeof(WorldComponent)).And.Member(typeof(IncompleteComponent))
|
||||
);
|
||||
Assert.That(
|
||||
serviceManager.GetComponents<IWorldContract>(true),
|
||||
Has.Member(typeof(WorldComponent)).And.No.Member(typeof(IncompleteComponent))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the GetComponents() method can cope with two components
|
||||
/// that have a circular dependency through their services.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCircularDependency() {
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the right exception is thrown if the non-generic GetService()
|
||||
/// is used on a value type
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetComponentOnValueType() {
|
||||
RepositoryTypeLister typeLister = new RepositoryTypeLister();
|
||||
ServiceManager serviceManager = new ServiceManager(typeLister);
|
||||
typeLister.Repository.AddAssembly(typeof(int).Assembly);
|
||||
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { serviceManager.GetService(typeof(int)); }
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
||||
|
||||
#endif // UNITTEST
|
|
@ -1,326 +0,0 @@
|
|||
#region CPL License
|
||||
/*
|
||||
Nuclex Framework
|
||||
Copyright (C) 2002-2010 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;
|
||||
|
||||
#if ENABLE_SERVICEMANAGER
|
||||
|
||||
namespace Nuclex.Support.Services {
|
||||
|
||||
// Allow Dependency on Container
|
||||
// public Foo(IServiceProvider serviceProvider)
|
||||
// public Foo(IserviceLocator serviceLocator)
|
||||
// public Foo(Container container)
|
||||
|
||||
/// <summary>
|
||||
/// Inversion of Control container that manages the services of an application
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is a very lightweight and simple inversion of control container that
|
||||
/// relieves components of their duty to track down implementations for the services
|
||||
/// they require to function. It will help with lazy initialization and prevent
|
||||
/// components from becoming cross-linked balls of spaghetti references.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Here's a short list of the terms used throughout this container and their
|
||||
/// specific meaning in this context.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <term>Service</term>
|
||||
/// <description>
|
||||
/// Defined by an interface (service contract) and provided by a component
|
||||
/// that implements the service contract. A service provides some kind of
|
||||
/// utility to the application, for example it could provide access to
|
||||
/// a data base or allow other components to control certain aspects of
|
||||
/// the application.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Contract</term>
|
||||
/// <description>
|
||||
/// Interface defining the behavior that a service implementation has to
|
||||
/// follow. In order for a component to become a suitable candidate for
|
||||
/// providing a specific service, it has to implement the service contract
|
||||
/// interface and should rigorously follow its specifications.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Component</term>
|
||||
/// <description>
|
||||
/// A component is simply a class that implements one or more service
|
||||
/// contracts. The service manager will created instances of these classes
|
||||
/// when all their dependencies can be provided for and an implementation
|
||||
/// of their service contract is requested.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public partial class ServiceManager : IServiceProvider {
|
||||
|
||||
#region class Contract
|
||||
|
||||
/// <summary>Stores the settings for an individual contract</summary>
|
||||
private class Contract {
|
||||
|
||||
/// <summary>
|
||||
/// Factory by which instances of the contract implementation can be created
|
||||
/// </summary>
|
||||
public IAbstractFactory Factory;
|
||||
|
||||
/// <summary>How instances of the implementation are to be managed</summary>
|
||||
public Instancing Instancing;
|
||||
|
||||
/// <summary>Single global instance of the contract implementation</summary>
|
||||
/// <remarks>
|
||||
/// Used only if <paramref name="Instancing" /> is set to Singleton
|
||||
/// </remarks>
|
||||
public object SingletonInstance;
|
||||
|
||||
/// <summary>Thread-local instance of the contract implementation</summary>
|
||||
/// <remarks>
|
||||
/// Used only if <paramref name="Instancing" />is set to InstancePerThread
|
||||
/// </remarks>
|
||||
public object ThreadLocalInstance {
|
||||
get {
|
||||
initializeThreadLocalData();
|
||||
return Thread.GetData(this.threadLocalDataSlot);
|
||||
}
|
||||
set {
|
||||
initializeThreadLocalData();
|
||||
Thread.SetData(this.threadLocalDataSlot, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Initializes the thread-local data slot</summary>
|
||||
private void initializeThreadLocalData() {
|
||||
if(this.threadLocalDataSlot == null) {
|
||||
lock(this) {
|
||||
if(this.threadLocalDataSlot == null) {
|
||||
this.threadLocalDataSlot = Thread.AllocateDataSlot();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Arguments to be passed to the component constructor</summary>
|
||||
private Dictionary<string, object> arguments;
|
||||
|
||||
/// <summary>Data slot for thread local storage</summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
private volatile LocalDataStoreSlot threadLocalDataSlot;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class Contract
|
||||
|
||||
#if WINDOWS
|
||||
|
||||
/// <summary>Initializes a new service manager</summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
public ServiceManager() : this(new AppDomainTypeLister()) { }
|
||||
|
||||
#endif // WINDOWS
|
||||
|
||||
/// <summary>Initializes a new service manager</summary>
|
||||
/// <param name="typeLister">
|
||||
/// Type lister providing the types considered by the service manager for
|
||||
/// obtaining contract implementations.
|
||||
/// </param>
|
||||
public ServiceManager(ITypeLister typeLister) {
|
||||
this.typeLister = typeLister;
|
||||
this.contracts = new Dictionary<Type, Contract>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all available implementations for the specified contract
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new enumerator for the available contract implementations
|
||||
/// </returns>
|
||||
public IEnumerable<Type> GetComponents<ContractType>() 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all available implementations for the specified contract
|
||||
/// </summary>
|
||||
/// <param name="completeOnly">
|
||||
/// If true, only services whose dependencies can be completely
|
||||
/// satisfied by the container are returned.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A new enumerator for the available contract implementations
|
||||
/// </returns>
|
||||
public IEnumerable<Type> GetComponents<ContractType>(bool completeOnly)
|
||||
where ContractType : class {
|
||||
if(completeOnly) {
|
||||
return filterCompleteComponents(GetComponents<ContractType>());
|
||||
} else {
|
||||
return GetComponents<ContractType>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters a list of components so only components whose dependencies can be
|
||||
/// completely provided are enumerated
|
||||
/// </summary>
|
||||
/// <param name="types">Enumerable type list that will be filtered</param>
|
||||
/// <returns>
|
||||
/// Only those components whose dependencies can be completely provided
|
||||
/// </returns>
|
||||
private IEnumerable<Type> filterCompleteComponents(IEnumerable<Type> types) {
|
||||
foreach(Type type in types) {
|
||||
|
||||
bool isCandidate =
|
||||
(!type.IsValueType) &&
|
||||
(!type.IsAbstract) &&
|
||||
(type.IsPublic || type.IsNestedPublic);
|
||||
|
||||
if(isCandidate) {
|
||||
|
||||
ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public);
|
||||
|
||||
|
||||
|
||||
// If a contract has been
|
||||
Contract contract;
|
||||
if(this.contracts.TryGetValue(type, out contract)) {
|
||||
yield return type;
|
||||
} else {
|
||||
}
|
||||
|
||||
yield return type;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the adjustment of the container's behavior in regard to
|
||||
/// the specified contract
|
||||
/// </summary>
|
||||
/// <typeparam name="ContractType">
|
||||
/// Contract for which the behavior will be adjusted
|
||||
/// </typeparam>
|
||||
/// <returns>
|
||||
/// A context object through which the behavior of the container can be
|
||||
/// adjusted for the specified type
|
||||
/// </returns>
|
||||
public ForContext<ContractType> For<ContractType>() where ContractType : class {
|
||||
return new ForContext<ContractType>(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the adjustment of the container's behavior in regard to
|
||||
/// the specified contract
|
||||
/// </summary>
|
||||
/// <param name="contractType">
|
||||
/// Contract for which the behavior will be adjusted
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A context object through which the behavior of the container can be
|
||||
/// adjusted for the specified type
|
||||
/// </returns>
|
||||
public ForContext For(Type contractType) {
|
||||
return new ForContext(this, contractType);
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the service of the specified type</summary>
|
||||
/// <typeparam name="ContractType">
|
||||
/// Contract for which the service will be retrieved
|
||||
/// </typeparam>
|
||||
/// <returns>The service for the specified contract</returns>
|
||||
public ContractType GetService<ContractType>() where ContractType : class {
|
||||
return (ContractType)GetService(typeof(ContractType));
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the service of the specified type</summary>
|
||||
/// <param name="contractType">
|
||||
/// Contract for which the service will be retrieved
|
||||
/// </param>
|
||||
/// <returns>The service for the specified contract</returns>
|
||||
public object GetService(Type contractType) {
|
||||
Contract c = resolveContract(contractType);
|
||||
return c.Factory.CreateInstance(); // TODO: Honor the contract settings
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves all dependencies required to create a service for a contract
|
||||
/// </summary>
|
||||
/// <param name="contractType">
|
||||
/// Type of contract for which to resolve the implementation
|
||||
/// </param>
|
||||
/// <returns>The settings for the contract including a valid factory</returns>
|
||||
private Contract resolveContract(Type contractType) {
|
||||
if(contractType.IsValueType) {
|
||||
throw new ArgumentException(
|
||||
"Contracts have to be interfaces or classes", "contractType"
|
||||
);
|
||||
}
|
||||
/*
|
||||
Contract contract;
|
||||
if(this.contracts.TryGetValue(contractType, out contract)) {
|
||||
return contract;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>Lists all types partaking in the dependency injection</summary>
|
||||
private ITypeLister typeLister;
|
||||
/// <summary>Dictionary with settings for each individual contract</summary>
|
||||
private Dictionary<Type, Contract> contracts;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Services
|
||||
|
||||
#endif // ENABLE_SERVICEMANAGER
|
Loading…
Reference in New Issue
Block a user