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