diff --git a/CHANGELOG.md b/CHANGELOG.md index 1760c70438..885e339004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,10 +17,22 @@ Breaking Changes: - Removed obsolete ActAs, Parameters, Properties and ServiceOverrides methods from component registration (@fir3pho3nixx, #338) - Removed obsolete indexer, AddComponent*, AddFacility and Resolve methods from IKernel and IWindsorContainer (@fir3pho3nixx, #338) - Facility XML configuration specifying an 'id' attribute will now throw, it has been ignored since v3.0 (@fir3pho3nixx, #338) -- Removal of deprecated classes AllTypes and AllTypesOf (@fir3pho3nixx, #338) -- Removal of deprecated BasedOn methods that reset registrations when fluently chained (@fir3pho3nixx, #338) -- Removal of deprecated member LifestyleHandlerType on CustomLifestyleAttribute (@fir3pho3nixx, #338) +- Removed deprecated classes `AllTypes` and `AllTypesOf` (@fir3pho3nixx, #338) +- Removed deprecated `BasedOn` methods that reset registrations when fluently chained (@fir3pho3nixx, #338) +- Removed deprecated member `LifestyleHandlerType` on `CustomLifestyleAttribute` (@fir3pho3nixx, #338) - Removed Event Wiring, Factory Support and Synchronize facilities (@jonorossi, #403) +- Arguments class and Resolve overloads refactor (@fir3pho3nixx, @jonorossi, #444) + - Removed `WindsorContainer.Resolve(object/IDictionary)` overloads in favour of new `WindsorContainer.Resolve(Arguments)` + - Reworked `Arguments` class, including to no longer implement `IDictionary` + - Removed `IArgumentsComparer[]` constructors from `Arguments` + - Added `WindsorContainer.Resolve(IEnumerable>)` extension methods + - Changed `CreationContext.AdditionalArguments` to use `Arguments` instead of `IDictionary` + - Replaced `ComponentDependencyRegistrationExtensions(Insert, InsertAnonymous, InsertTyped, InsertTypedCollection)` with `Add`, `AddNamed` and `AddTyped` `Arguments` instance methods + - Changed `ComponentRegistration.DependsOn` and `ComponentRegistration.DynamicParameters` to use `Arguments` via `DynamicParametersDelegate` + - Added `ComponentRegistration.DependsOn(Arguments)` overload + - Changed `ComponentModel` `CustomDependencies` and `ExtendedProperties` to use `Arguments` instead of `IDictionary` + - Changed `IComponentModelBuilder.BuildModel` to use `Arguments` instead of `IDictionary` + - Changed `ILazyComponentLoader.Load` to use `Arguments` instead of `IDictionary` ## 4.1.1 (2018-10-15) diff --git a/docs/arguments.md b/docs/arguments.md index 2e0f659b32..230560f1ef 100644 --- a/docs/arguments.md +++ b/docs/arguments.md @@ -2,47 +2,68 @@ ## The `Arguments` class -The `Arguments` class is used by Windsor to pass arguments [down the invocation pipeline](how-dependencies-are-resolved.md). The class is a simple implementation of non-generic `IDictionary`, but it has some useful capabilities. +The `Arguments` class is used by Windsor to pass arguments [down the invocation pipeline](how-dependencies-are-resolved.md). The class is a simple dictionary-like class, but it has some useful capabilities. -:information_source: **Custom `IDictionary` is respected:** When you call `container.Resolve` passing your own custom implementation of `IDictionary` Windsor will respect that and not replace it with `Arguments`. It is advised that you use `Arguments` though. +Resolution arguments are key/value pairs, keyed either by name (`string`) or type (`System.Type`). How the arguments are added to the `Arguments` collections determines how they are bound to dependencies during resolution. ### Constructors The class has several constructors: +```csharp +new Arguments(); // Empty collection +new Arguments(new Arguments())); // Copy constructor +``` -#### `namedArgumentsAsAnonymousType` - -You can pass named arguments as properties on anonymous type: +Collection initializers are supported, both named and typed arguments can be provided: ```csharp -new Arguments(new { logLevel = LogLevel.High }); +new Arguments { + { "Name", "John" }, + { "Age", 18 }, + { typeof(IService), new MyService() } +}; ``` -:information_source: **Named arguments are not case sensitive:** You can specify `logLevel`, `LogLevel` or even `LOGLEVEL` as property name. All named arguments are matched in case insensitive manner so in all cases the behavior will be the same. +### Fluent Interface -#### Array of `typedArguments` +#### Named Arguments -When you don't care about names of the dependencies you can pass them as array, in which case they will be matched by their type. +Arguments will be matched by a string key in a case insensitive manner. For example, `logLevel`, `LogLevel` and even `LOGLEVEL` as property names are all treated as one key. + +```csharp +new Arguments() + .AddNamed("key", 123456) + .AddNamed(new Dictionary { { "string-key", "string-value" } }); +``` +Named arguments can also be added from a plain old C# object or from properties of an anonymous type: ```csharp -new Arguments(new[] { LogLevel.High }); +new Arguments() + .AddProperties(myPOCO) // plain old C# object with public properties + .AddProperties(new { logLevel = LogLevel.High }); // anonymous type ``` -:information_source: **Typed arguments are matched exactly:** When you don't specify type of the dependency it's exact type will be used. So if you pass for example `MemoryStream` Windsor will try to match it to dependency of type `MemoryStream`, but not of the base type `Stream`. If you want to match it to `Stream` use `Insert` extension method. +#### Typed Arguments -#### Custom dictionary of arguments +Arguments can be matched by type as dependencies: -You can also pass already populated dictionary to `Arguments` in which case its values will be copied over. +```csharp +new Arguments() + .AddTyped(LogLevel.High, new AppConfig()) // params array + .AddTyped(typeof(MyClass), new MyClass()) + .AddTyped(new MyService()); +``` -### `Insert` extension method +:information_source: **Typed arguments are matched exactly:** When you don't specify the type of the argument, its concrete type will be used. For example, if you pass a `MemoryStream` it will only match to a dependency of type `MemoryStream`, but not of the base type `Stream`. If you want to match it to `Stream` specify the type explicitly. -In addition to `Arguments` class there's also `Insert` extension method that extends `IDictionary`. It has several overloads that let you fluently insert values into the dictionary. +#### Named and/or Typed Arguments Collection +A collection implementing the generic `IDictionary` containing named and/or typed arguments can be added to an `Arguments` instance: ```csharp -args.Insert(someMemoryStream) - .Insert("name", someNamedArgument) - .Insert(new[] { multiple, typed, arguments}) - .Insert(new { multiple = typed, arguments = also}); -``` +var map = new Dictionary(); +map.Add("string-key", 123456); +map.Add(typeof(MyType), 123456); -:information_source: **Insert overwrites:** When item under given key already exists `Insert` will overwrite it. \ No newline at end of file +new Arguments() + .Add(map); +``` diff --git a/src/Castle.Facilities.WcfIntegration.Tests/Client/WcfClientFixture.cs b/src/Castle.Facilities.WcfIntegration.Tests/Client/WcfClientFixture.cs index 579e375747..e52065e51e 100644 --- a/src/Castle.Facilities.WcfIntegration.Tests/Client/WcfClientFixture.cs +++ b/src/Castle.Facilities.WcfIntegration.Tests/Client/WcfClientFixture.cs @@ -31,6 +31,7 @@ namespace Castle.Facilities.WcfIntegration.Tests using Castle.Facilities.WcfIntegration.Demo; using Castle.Facilities.WcfIntegration.Tests.Behaviors; using Castle.Facilities.WcfIntegration.Tests.Components; + using Castle.MicroKernel; using Castle.MicroKernel.Facilities; using Castle.MicroKernel.Registration; using Castle.Services.Logging.Log4netIntegration; @@ -243,23 +244,23 @@ public void CanResolveClientAssociatedWithChannelUsingSuppliedModel() )) { var client1 = clientContainer.Resolve("operations", - new + Arguments.FromProperties(new { Model = new DefaultClientModel { Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()) .At("net.tcp://localhost/Operations2") } - }); + })); var client2 = clientContainer.Resolve("operations", - new + Arguments.FromProperties(new { Model = new DefaultClientModel() { Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()) .At("net.tcp://localhost/Operations2") } - }); + })); Assert.AreEqual(28, client1.GetValueFromConstructor()); Assert.AreEqual(28, client2.GetValueFromConstructor()); clientContainer.Release(client1); @@ -291,10 +292,10 @@ public void CanResolveClientAssociatedWithChannelUsingSuppliedEndpoint() )) { var tracker = ReferenceTracker.Track(() => clientContainer.Resolve("operations", - new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") })); + Arguments.FromProperties(new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") }))); var client2 = clientContainer.Resolve("operations", - new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") }); + Arguments.FromProperties(new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") })); Assert.AreEqual(28, tracker.AssertStillReferencedAndDo(client1 => client1.GetValueFromConstructor())); Assert.AreEqual(28, client2.GetValueFromConstructor()); @@ -325,23 +326,23 @@ public void CanLazilyResolveClientAssociatedWithChannelUsingSuppliedModel() .AddFacility(f => f.CloseTimeout = TimeSpan.Zero)) { var client1 = clientContainer.Resolve( - new + Arguments.FromProperties(new { Model = new DefaultClientModel { Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()) .At("net.tcp://localhost/Operations2") } - }); + })); var client2 = clientContainer.Resolve( - new + Arguments.FromProperties(new { Model = new DefaultClientModel() { Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()) .At("net.tcp://localhost/Operations2") } - }); + })); Assert.AreEqual(28, client1.GetValueFromConstructor()); Assert.AreEqual(28, client2.GetValueFromConstructor()); clientContainer.Release(client1); @@ -368,9 +369,9 @@ public void CanLazilyResolveClientAssociatedWithChannelUsingSuppliedEndpoint() .AddFacility(f => f.CloseTimeout = TimeSpan.Zero)) { var tracker = ReferenceTracker.Track(() => clientContainer.Resolve("operations", - new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") })); + Arguments.FromProperties(new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") }))); var client2 = clientContainer.Resolve("operations", - new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") }); + Arguments.FromProperties(new { Endpoint = WcfEndpoint.At("net.tcp://localhost/Operations2") })); Assert.AreEqual(28, tracker.AssertStillReferencedAndDo(client1 => client1.GetValueFromConstructor())); Assert.AreEqual(28, client2.GetValueFromConstructor()); @@ -536,14 +537,14 @@ public void WillRecoverFromAnUnhandledExceptionWithChannelUsingSuppliedModel() )) { var client = clientContainer.Resolve("operations", - new + Arguments.FromProperties(new { Model = new DefaultClientModel { Endpoint = WcfEndpoint.BoundTo(new NetTcpBinding()) .At("net.tcp://localhost/Operations2") } - }); + })); try { client.ThrowException(); diff --git a/src/Castle.Facilities.WcfIntegration/Client/WcfClientComponentLoader.cs b/src/Castle.Facilities.WcfIntegration/Client/WcfClientComponentLoader.cs index cdc302dee4..2ca914cf9d 100644 --- a/src/Castle.Facilities.WcfIntegration/Client/WcfClientComponentLoader.cs +++ b/src/Castle.Facilities.WcfIntegration/Client/WcfClientComponentLoader.cs @@ -15,16 +15,16 @@ namespace Castle.Facilities.WcfIntegration { using System; - using System.Collections; using System.Linq; using Castle.Facilities.WcfIntegration.Internal; + using Castle.MicroKernel; using Castle.MicroKernel.Facilities; using Castle.MicroKernel.Registration; using Castle.MicroKernel.Resolvers; public class WcfClientComponentLoader : ILazyComponentLoader { - public IRegistration Load(string key, Type service, IDictionary arguments) + public IRegistration Load(string key, Type service, Arguments arguments) { if (service == typeof(IWcfClientFactory)) { diff --git a/src/Castle.Facilities.WcfIntegration/Client/WcfClientFactorySelector.cs b/src/Castle.Facilities.WcfIntegration/Client/WcfClientFactorySelector.cs index 11bec0a352..90f115f742 100644 --- a/src/Castle.Facilities.WcfIntegration/Client/WcfClientFactorySelector.cs +++ b/src/Castle.Facilities.WcfIntegration/Client/WcfClientFactorySelector.cs @@ -44,7 +44,7 @@ public Func SelectComponent(MethodInfo argument = WcfEndpoint.At((Uri)argument); } - var args = new HybridDictionary { { Guid.NewGuid().ToString(), argument } }; + var args = new Arguments { { Guid.NewGuid().ToString(), argument } }; if (key == null) { diff --git a/src/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs b/src/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs index b00678987d..2fdef8e962 100644 --- a/src/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs +++ b/src/Castle.Facilities.WcfIntegration/Internal/WcfUtils.cs @@ -255,17 +255,19 @@ public static bool IsBehaviorExtension(object behavior) behavior is IOperationBehavior || behavior is IEndpointBehavior; } - public static IEnumerable FindDependencies(IDictionary dependencies) + public static IEnumerable FindDependencies(Arguments dependencies) { return FindDependencies(dependencies, null); } - public static IEnumerable FindDependencies(IDictionary dependencies, Predicate test) + public static IEnumerable FindDependencies(Arguments dependencies, Predicate test) { if (dependencies != null) { - foreach (object dependency in dependencies.Values) + foreach (var pair in dependencies) { + var dependency = pair.Value; + if (dependency is T) { var candidate = (T)dependency; diff --git a/src/Castle.Windsor.Tests/Bugs/IoC-138.cs b/src/Castle.Windsor.Tests/Bugs/IoC-138.cs index 16eb1cd047..d06423d6cb 100644 --- a/src/Castle.Windsor.Tests/Bugs/IoC-138.cs +++ b/src/Castle.Windsor.Tests/Bugs/IoC-138.cs @@ -16,6 +16,7 @@ namespace Castle.Windsor.Tests.Bugs { using System.Collections.Generic; + using Castle.MicroKernel; using Castle.MicroKernel.Registration; using NUnit.Framework; @@ -28,10 +29,12 @@ public void TestResolveSubComponentInConstructorWithParameters() { var container = new WindsorContainer(); ServiceLocator.Container = container; - container.Register(Component.For().Named("A"), + container.Register(Component.For().Named("A"), Component.For().Named("B")); - var component = container.Resolve(new Dictionary { { "test", "bla" } }); + var component = container.Resolve( + new Arguments { { "test", "bla" } }); + Assert.IsNotNull(component.Other); } @@ -47,13 +50,13 @@ public static class ServiceLocator public static IWindsorContainer Container { get; set; } } - public class UsesServiceLocaator + public class UsesServiceLocator { private readonly DependsOnStringTest2 other; - public UsesServiceLocaator(string test) + public UsesServiceLocator(string test) { - other = ServiceLocator.Container.Resolve(new Dictionary { { "test2", "bla" } }); + other = ServiceLocator.Container.Resolve(new Arguments { { "test2", "bla" } }); } public DependsOnStringTest2 Other diff --git a/src/Castle.Windsor.Tests/ByRefDependenciesTestCase.cs b/src/Castle.Windsor.Tests/ByRefDependenciesTestCase.cs index 807515f92b..a0904a8f7c 100644 --- a/src/Castle.Windsor.Tests/ByRefDependenciesTestCase.cs +++ b/src/Castle.Windsor.Tests/ByRefDependenciesTestCase.cs @@ -14,6 +14,7 @@ namespace Castle.Windsor.Tests { + using Castle.MicroKernel; using Castle.MicroKernel.Registration; using Castle.Windsor.Tests.ClassComponents; @@ -38,7 +39,7 @@ public void Can_resolve_type_with_by_ref_dependency_provided_inline() { Container.Register(Component.For()); - Container.Resolve(new { a = new A() }); + Container.Resolve(Arguments.FromProperties(new { a = new A() })); } [Test] @@ -46,7 +47,7 @@ public void Can_resolve_type_with_by_ref_dependency_provided_inline_via_anonymou { Container.Register(Component.For()); - Container.Resolve(new { a = new A() }); + Container.Resolve(Arguments.FromProperties(new { a = new A() })); } } } \ No newline at end of file diff --git a/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorByClosedArgumentType.cs b/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorByClosedArgumentType.cs index 3224abb3cd..6d3e9a80c5 100644 --- a/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorByClosedArgumentType.cs +++ b/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorByClosedArgumentType.cs @@ -15,7 +15,6 @@ namespace CastleTests.Facilities.TypedFactory.Selectors { using System; - using System.Collections; using System.Reflection; using Castle.Facilities.TypedFactory; @@ -29,10 +28,10 @@ public SelectorByClosedArgumentType() FallbackToResolveByTypeIfNameNotFound = true; } - protected override IDictionary GetArguments(MethodInfo method, object[] arguments) + protected override Arguments GetArguments(MethodInfo method, object[] arguments) { //a condition checking if it's actually a method we want to be in should go here - return new Arguments(arguments); + return new Arguments().AddTyped(arguments); } protected override Type GetComponentType(MethodInfo method, object[] arguments) diff --git a/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorById.cs b/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorById.cs index 7c7f6c305f..ff2ee0603b 100644 --- a/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorById.cs +++ b/src/Castle.Windsor.Tests/Facilities/TypedFactory/Selectors/SelectorById.cs @@ -22,7 +22,7 @@ namespace Castle.Windsor.Tests.Facilities.TypedFactory.Selectors public class SelectorById : DefaultTypedFactoryComponentSelector { - protected override IDictionary GetArguments(MethodInfo method, object[] arguments) + protected override Arguments GetArguments(MethodInfo method, object[] arguments) { if (method.Name.Equals("ComponentNamed")) { diff --git a/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryDelegatesTestCase.cs b/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryDelegatesTestCase.cs index e9afc9704e..e60b3c574b 100644 --- a/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryDelegatesTestCase.cs +++ b/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryDelegatesTestCase.cs @@ -95,7 +95,7 @@ public void Can_resolve_component_depending_on_delegate_when_inline_argumens_are Container.Register(Component.For(), Component.For()); - Container.Resolve(new { additionalArgument = 5 }); + Container.Resolve(Arguments.FromProperties(new { additionalArgument = 5 })); } [Test] @@ -149,7 +149,7 @@ public void Can_resolve_two_services_depending_on_identical_delegates() { Container.Register(Component.For().LifeStyle.Transient, Component.For(), - Component.For().DependsOn(new Arguments().InsertTyped(5))); + Component.For().DependsOn(new Arguments().AddTyped(5))); var one = Container.Resolve(); var two = Container.Resolve(); one.GetFoo(); @@ -161,7 +161,7 @@ public void Can_resolve_two_services_depending_on_identical_delegates_via_interf { Container.Register(Component.For().LifeStyle.Transient, Component.For(), - Component.For().DependsOn(new Arguments().InsertTyped(5)), + Component.For().DependsOn(new Arguments().AddTyped(5)), Component.For().AsFactory()); var factory = Container.Resolve(); diff --git a/src/Castle.Windsor.Tests/HelpfulExceptionsOnResolveTestCase.cs b/src/Castle.Windsor.Tests/HelpfulExceptionsOnResolveTestCase.cs index 25bee22114..f2ddde353d 100644 --- a/src/Castle.Windsor.Tests/HelpfulExceptionsOnResolveTestCase.cs +++ b/src/Castle.Windsor.Tests/HelpfulExceptionsOnResolveTestCase.cs @@ -74,7 +74,7 @@ public void No_resolvable_constructor_with_inline_arguments() { Container.Register(Component.For()); - var fakeArgument = new Arguments(new[] { new object() }); + var fakeArgument = new Arguments().AddTyped(new object()); var exception = Assert.Throws(() => Container.Resolve(fakeArgument)); var message = diff --git a/src/Castle.Windsor.Tests/LazyComponentsTestCase.cs b/src/Castle.Windsor.Tests/LazyComponentsTestCase.cs index afefad96b1..80b8fee15f 100644 --- a/src/Castle.Windsor.Tests/LazyComponentsTestCase.cs +++ b/src/Castle.Windsor.Tests/LazyComponentsTestCase.cs @@ -164,9 +164,9 @@ public void Can_resolve_lazy_component_requiring_arguments_inline() Container.Register(Component.For()); var a = new A(); - var arguments = new Arguments(new object[] { a }); + var arguments = new Arguments().AddTyped(a); var missingArguments = Container.Resolve>(); - var hasArguments = Container.Resolve>(new { arguments }); + var hasArguments = Container.Resolve>(Arguments.FromProperties(new { arguments })); B ignore; Assert.Throws(() => ignore = missingArguments.Value); @@ -181,7 +181,7 @@ public void Can_resolve_lazy_component_with_override() Container.Register(Component.For().Named("1"), Component.For().Named("2")); - var lazyA = Container.Resolve>(new { overrideComponentName = "2" }); + var lazyA = Container.Resolve>(Arguments.FromProperties(new { overrideComponentName = "2" })); var a2 = Container.Resolve("2"); Assert.AreSame(a2, lazyA.Value); diff --git a/src/Castle.Windsor.Tests/LazyLoadingTestCase.cs b/src/Castle.Windsor.Tests/LazyLoadingTestCase.cs index ca6dd0bdee..4ee817036b 100644 --- a/src/Castle.Windsor.Tests/LazyLoadingTestCase.cs +++ b/src/Castle.Windsor.Tests/LazyLoadingTestCase.cs @@ -52,7 +52,7 @@ public void Can_lazily_resolve_dependency() public void Can_lazily_resolve_explicit_dependency() { Container.Register(Component.For().ImplementedBy()); - var component = Container.Resolve(new Arguments().Insert("parameter", "Hello")); + var component = Container.Resolve(new Arguments().AddNamed("parameter", "Hello")); Assert.AreEqual("Hello", component.Parameter); } @@ -126,7 +126,7 @@ public class ABLoaderWithGuardClause : ILazyComponentLoader { public bool CanLoadNow { get; set; } - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { Assert.True(CanLoadNow); @@ -140,7 +140,7 @@ public IRegistration Load(string name, Type service, IDictionary arguments) public class ABLoader : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { if (service == typeof(A) || service == typeof(B)) { @@ -159,7 +159,7 @@ public LoaderWithDependency(IEmployee employee) this.employee = employee; } - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { return null; } @@ -167,7 +167,7 @@ public IRegistration Load(string name, Type service, IDictionary arguments) public class SlowLoader : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary argume) + public IRegistration Load(string name, Type service, Arguments argume) { Thread.Sleep(200); return Component.For(service).Named(name); @@ -176,7 +176,7 @@ public IRegistration Load(string name, Type service, IDictionary argume) public class LoaderForDefaultImplementations : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { if (!service.GetTypeInfo().IsDefined(typeof(DefaultImplementationAttribute))) { @@ -191,7 +191,7 @@ public IRegistration Load(string name, Type service, IDictionary arguments) public class LoaderUsingDependency : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { return Component.For(service).DependsOn(arguments); } diff --git a/src/Castle.Windsor.Tests/MicroKernel/ArgumentsTestCase.cs b/src/Castle.Windsor.Tests/MicroKernel/ArgumentsTestCase.cs index 4029fc37d6..2f06f9b428 100644 --- a/src/Castle.Windsor.Tests/MicroKernel/ArgumentsTestCase.cs +++ b/src/Castle.Windsor.Tests/MicroKernel/ArgumentsTestCase.cs @@ -15,11 +15,9 @@ namespace Castle.Windsor.Tests.MicroKernel { using System; - using System.Collections; using System.Collections.Generic; using Castle.MicroKernel; - using Castle.MicroKernel.Context; using Castle.MicroKernel.Registration; using Castle.Windsor.Tests.Components; @@ -32,15 +30,12 @@ namespace Castle.Windsor.Tests.MicroKernel public class ArgumentsTestCase : AbstractContainerTestCase { [Test] - public void By_default_any_type_as_key_is_supported() + public void Any_type_as_key_is_not_supported() { - var arguments = new Arguments(new CustomStringComparer()); - var key = new object(); - var value = "foo"; - - arguments.Add(key, value); + var arguments = new Arguments(); - Assert.AreEqual("foo", arguments[key]); + Assert.Throws(delegate { arguments.Add(123, 321); }); + Assert.Throws(delegate { arguments.Add(new object(), "value"); }); } [Test] @@ -52,7 +47,7 @@ public void Can_have_dictionary_as_inline_dependency() var dictionaryProperty = new Dictionary(); - var obj = container.Resolve(new { dictionaryProperty }); + var obj = container.Resolve(Arguments.FromProperties(new { dictionaryProperty })); Assert.AreSame(dictionaryProperty, obj.DictionaryProperty); } @@ -62,7 +57,7 @@ public void Can_satisfy_nullable_property_dependency() { Container.Register(Component.For()); - var arguments = new Arguments().Insert("SomeVal", 5); + var arguments = new Arguments().AddNamed("SomeVal", 5); var s = Container.Resolve(arguments); Assert.IsNotNull(s.SomeVal); @@ -74,7 +69,7 @@ public void Can_satisfy_nullable_ctor_dependency() { Container.Register(Component.For()); - var s = Container.Resolve(new Arguments().Insert("foo", 5d)); + var s = Container.Resolve(new Arguments().AddNamed("foo", 5d)); Assert.IsNotNull(s); } @@ -87,33 +82,7 @@ public void Can_mix_hashtable_parameters_and_configuration_parameters() .DependsOn(Parameter.ForKey("x").Eq("abc")) ); - Container.Resolve(new Arguments().Insert("y", 1)); - } - - [Test] - public void Custom_stores_get_picked_over_default_ones() - { - var arguments = new Arguments(new CustomStringComparer()); - var key = "foo"; - var value = new object(); - - arguments.Add(key, value); - - Assert.AreEqual(value, arguments["boo!"]); - } - - [Test] - public void Custom_stores_get_picked_over_default_ones_in_clone() - { - var arguments = new Arguments(new CustomStringComparer()); - var key = "foo"; - var value = new object(); - - arguments.Add(key, value); - - var clone = arguments.Clone(); - - Assert.AreEqual(value, clone["boo!"]); + Container.Resolve(new Arguments().AddNamed("y", 1)); } [Test] @@ -157,29 +126,4 @@ public void Handles_string_as_key_case_insensitive() Assert.IsTrue(arguments.Contains(key.ToUpper())); } } - - public class CustomStringComparer : IArgumentsComparer - { - public bool RunEqualityComparison(object x, object y, out bool areEqual) - { - if (x is string) - { - areEqual = true; - return true; - } - areEqual = false; - return false; - } - - public bool RunHasCodeCalculation(object o, out int hashCode) - { - if (o is string) - { - hashCode = "boo!".GetHashCode(); - return true; - } - hashCode = 0; - return false; - } - } } \ No newline at end of file diff --git a/src/Castle.Windsor.Tests/MicroKernelTestCase.cs b/src/Castle.Windsor.Tests/MicroKernelTestCase.cs index 54f034a8d0..4b0eb5dd21 100644 --- a/src/Castle.Windsor.Tests/MicroKernelTestCase.cs +++ b/src/Castle.Windsor.Tests/MicroKernelTestCase.cs @@ -56,7 +56,7 @@ public void AddClassThatHasTwoParametersOfSameTypeAndNoOverloads() { Kernel.Register(Component.For(typeof(ClassWithTwoParametersWithSameType)).Named("test")); Kernel.Register(Component.For().ImplementedBy(typeof(CommonImpl1)).Named("test2")); - var resolved = Kernel.Resolve(typeof(ClassWithTwoParametersWithSameType), new Dictionary()); + var resolved = Kernel.Resolve(typeof(ClassWithTwoParametersWithSameType)); Assert.IsNotNull(resolved); } @@ -112,7 +112,7 @@ public void AdditionalParametersShouldNotBePropagatedInTheDependencyChain() Component.For().ImplementedBy().Named("cust").LifeStyle.Transient); Kernel.Register(Component.For().Named("custex").LifeStyle.Transient); - var dictionary = new Dictionary { { "Name", "name" }, { "Address", "address" }, { "Age", "18" } }; + var dictionary = new Arguments { { "Name", "name" }, { "Address", "address" }, { "Age", "18" } }; var customer = Kernel.Resolve("cust", dictionary); Assert.AreEqual("name", customer.Name); @@ -203,7 +203,7 @@ public void ResolveAll_resolves_when_dependency_provideded_dynamically() { Kernel.Register(Component.For() .ImplementedBy() - .DynamicParameters((k, d) => d.Insert(typeof(ICustomer), new CustomerImpl())) + .DynamicParameters((k, d) => d.AddTyped(typeof(ICustomer), new CustomerImpl())) ); var services = Kernel.ResolveAll(); @@ -214,7 +214,7 @@ public void ResolveAll_resolves_when_dependency_provideded_dynamically() public void ResolveAll_resolves_when_dependency_provideded_inline() { Kernel.Register(Component.For().ImplementedBy(typeof(CommonImplWithDependency)).Named("test")); - var services = Kernel.ResolveAll(new Arguments().Insert("customer", new CustomerImpl())); + var services = Kernel.ResolveAll(new Arguments().AddNamed("customer", new CustomerImpl())); Assert.AreEqual(1, services.Length); } @@ -230,7 +230,7 @@ public void ResolveUsingAddionalParametersForConfigurationInsteadOfServices() Assert.IsNull(customer.Name); Assert.AreEqual(0, customer.Age); - var dictionary = new Dictionary { { "Name", "name" }, { "Address", "address" }, { "Age", "18" } }; + var dictionary = new Arguments { { "Name", "name" }, { "Address", "address" }, { "Age", "18" } }; customer = Kernel.Resolve("cust", dictionary); Assert.AreEqual("name", customer.Name); @@ -245,8 +245,7 @@ public void ResolveViaGenerics() Kernel.Register(Component.For().ImplementedBy().Named("cust2")); var customer = Kernel.Resolve("cust"); - var dictionary = new Dictionary - { + var dictionary = new Arguments { { "name", "customer2Name" }, { "address", "customer2Address" }, { "age", 18 } diff --git a/src/Castle.Windsor.Tests/Pools/PooledLifestyleManagerTestCase.cs b/src/Castle.Windsor.Tests/Pools/PooledLifestyleManagerTestCase.cs index 9c7c411bf3..ec4593e9e1 100644 --- a/src/Castle.Windsor.Tests/Pools/PooledLifestyleManagerTestCase.cs +++ b/src/Castle.Windsor.Tests/Pools/PooledLifestyleManagerTestCase.cs @@ -59,10 +59,10 @@ public void DisposePoolDisposesTrackedComponents() var result = false; var container = new WindsorContainer(); container.Register(Component.For().LifestylePooled(1, 5)); - container.Release(container.Resolve(new + container.Release(container.Resolve(Arguments.FromProperties(new { disposeAction = new Action(() => { result = true; }) - })); + }))); // Act. container.Dispose(); @@ -383,16 +383,6 @@ public IKernel AddFacility(string key, IFacility facility) throw new NotImplementedException(); } - public object Resolve(string key, object argumentsAsAnonymousType) - { - throw new NotImplementedException(); - } - - public object Resolve(string key, IDictionary arguments) - { - throw new NotImplementedException(); - } - public IComponentModelBuilder ComponentModelBuilder { get; private set; } public IConfigurationStore ConfigurationStore { get; set; } public GraphNode[] GraphNodes { get; private set; } @@ -509,12 +499,7 @@ public object Resolve(Type service) throw new NotImplementedException(); } - public object Resolve(Type service, IDictionary arguments) - { - throw new NotImplementedException(); - } - - public object Resolve(Type service, object argumentsAsAnonymousType) + public object Resolve(Type service, Arguments arguments) { throw new NotImplementedException(); } @@ -524,12 +509,7 @@ public object Resolve(string key, Type service) throw new NotImplementedException(); } - public T Resolve(IDictionary arguments) - { - throw new NotImplementedException(); - } - - public T Resolve(object argumentsAsAnonymousType) + public T Resolve(Arguments arguments) { throw new NotImplementedException(); } @@ -544,12 +524,12 @@ public T Resolve(string key) throw new NotImplementedException(); } - public T Resolve(string key, IDictionary arguments) + public T Resolve(string key, Arguments arguments) { throw new NotImplementedException(); } - public object Resolve(string key, Type service, IDictionary arguments) + public object Resolve(string key, Type service, Arguments arguments) { throw new NotImplementedException(); } @@ -559,12 +539,7 @@ public Array ResolveAll(Type service) throw new NotImplementedException(); } - public Array ResolveAll(Type service, IDictionary arguments) - { - throw new NotImplementedException(); - } - - public Array ResolveAll(Type service, object argumentsAsAnonymousType) + public Array ResolveAll(Type service, Arguments arguments) { throw new NotImplementedException(); } @@ -574,12 +549,7 @@ public TService[] ResolveAll() throw new NotImplementedException(); } - public TService[] ResolveAll(IDictionary arguments) - { - throw new NotImplementedException(); - } - - public TService[] ResolveAll(object argumentsAsAnonymousType) + public TService[] ResolveAll(Arguments arguments) { throw new NotImplementedException(); } diff --git a/src/Castle.Windsor.Tests/Registration/AllTypesTestCase.cs b/src/Castle.Windsor.Tests/Registration/AllTypesTestCase.cs index 89bea323cb..b66d7ffb1b 100644 --- a/src/Castle.Windsor.Tests/Registration/AllTypesTestCase.cs +++ b/src/Castle.Windsor.Tests/Registration/AllTypesTestCase.cs @@ -446,7 +446,7 @@ public void RegisterAssemblyTypes_WhenTypeInMissingNamespace_NotRegisteredInCont { Kernel.Register( Classes.FromAssembly(GetCurrentAssembly()) - .Where(Component.IsInNamespace("Castle.MicroKernel.Tests.FooBar")) + .Where(Component.IsInNamespace("Castle.MicroKernel.Tests.AnyClass")) .WithService.FirstInterface() ); diff --git a/src/Castle.Windsor.Tests/Registration/DependsOnTestCase.cs b/src/Castle.Windsor.Tests/Registration/DependsOnTestCase.cs index 2da0373675..11f793b5be 100644 --- a/src/Castle.Windsor.Tests/Registration/DependsOnTestCase.cs +++ b/src/Castle.Windsor.Tests/Registration/DependsOnTestCase.cs @@ -68,7 +68,7 @@ public void can_register_value_from_a_resource_file_with_resourceManager() public void Can_register_configuration_parameters_from_dynamic_parameters_inline() { Container.Register(Component.For() - .DependsOn((k, d) => d.InsertAnonymous(new { arg1 = "a string", arg2 = 42 }))); + .DependsOn((k, d) => d.AddProperties(new { arg1 = "a string", arg2 = 42 }))); var obj = Container.Resolve(); diff --git a/src/Castle.Windsor.Tests/Registration/DynamicParametersTestCase.cs b/src/Castle.Windsor.Tests/Registration/DynamicParametersTestCase.cs index 3474ed369a..fb1f1410d5 100644 --- a/src/Castle.Windsor.Tests/Registration/DynamicParametersTestCase.cs +++ b/src/Castle.Windsor.Tests/Registration/DynamicParametersTestCase.cs @@ -17,6 +17,7 @@ namespace Castle.MicroKernel.Tests.Registration using System; using System.Collections; using System.Collections.Generic; + using System.Collections.ObjectModel; using Castle.MicroKernel.Registration; using Castle.MicroKernel.Tests.ClassComponents; @@ -39,7 +40,7 @@ public void Arguments_are_case_insensitive_when_using_anonymous_object() wasCalled = true; })); - Kernel.Resolve(new Arguments().Insert("arg2", 2).Insert("arg1", "foo")); + Kernel.Resolve(new Arguments().AddNamed("arg2", 2).AddNamed("arg1", "foo")); Assert.IsTrue(wasCalled); } @@ -78,7 +79,7 @@ public void Can_mix_registration_and_call_site_parameters() Kernel.Register( Component.For().LifeStyle.Transient.DynamicParameters((k, d) => d["arg1"] = "foo")); - var component = Kernel.Resolve(new Arguments().Insert("arg2", 2)); + var component = Kernel.Resolve(new Arguments().AddNamed("arg2", 2)); Assert.AreEqual(2, component.Arg2); Assert.AreEqual("foo", component.Arg1); } @@ -96,7 +97,7 @@ public void Can_release_components_with_dynamic_parameters() }) .DynamicParameters((k, d) => { return kk => ++releaseCalled; })); - var component = Kernel.Resolve(new Arguments().Insert("arg2", 2)); + var component = Kernel.Resolve(new Arguments().AddNamed("arg2", 2)); Assert.AreEqual(2, component.Arg2); Assert.AreEqual("foo", component.Arg1); @@ -118,29 +119,13 @@ public void Can_release_generics_with_dynamic_parameters() }) .DynamicParameters((k, d) => { return kk => ++releaseCalled; })); - var component = Kernel.Resolve>(new Arguments().Insert("name", "bar")); + var component = Kernel.Resolve>(new Arguments().AddNamed("name", "bar")); Assert.AreEqual("foo", component.Name); Kernel.ReleaseComponent(component); Assert.AreEqual(2, releaseCalled); } - [Test] - public void DynamicParameters_will_not_enforce_passed_IDictionary_to_be_writeable() - { - var wasCalled = false; - Kernel.Register(Component.For().LifeStyle.Transient.DynamicParameters((k, d) => - { - Assert.Throws(typeof(NotSupportedException), () => - d.Add("foo", "It will throw")); - wasCalled = true; - })); - - Kernel.Resolve(new ReadOnlyDictionary()); - - Assert.IsTrue(wasCalled); - } - [Test] public void Should_handle_multiple_calls() { @@ -150,7 +135,7 @@ public void Should_handle_multiple_calls() .LifeStyle.Transient .DynamicParameters((k, d) => { d["arg1"] = arg1; }) .DynamicParameters((k, d) => { d["arg2"] = arg2; })); - var component = Kernel.Resolve(new Arguments().Insert("arg2", 2).Insert("arg1", "foo")); + var component = Kernel.Resolve(new Arguments().AddNamed("arg2", 2).AddNamed("arg1", "foo")); Assert.AreEqual(arg1, component.Arg1); Assert.AreEqual(arg2, component.Arg2); } @@ -165,7 +150,7 @@ public void Should_have_access_to_parameters_passed_from_call_site() arg1 = (string)d["arg1"]; arg2 = (int)d["arg2"]; })); - var component = Kernel.Resolve(new Arguments().Insert("arg2", 2).Insert("arg1", "foo")); + var component = Kernel.Resolve(new Arguments().AddNamed("arg2", 2).AddNamed("arg1", "foo")); Assert.AreEqual("foo", arg1); Assert.AreEqual(2, arg2); } @@ -187,7 +172,7 @@ public void Should_override_parameters_passed_from_call_site() d["arg1"] = arg1; d["arg2"] = arg2; })); - var component = Kernel.Resolve(new Arguments().Insert("arg2", 2).Insert("arg1", "foo")); + var component = Kernel.Resolve(new Arguments().AddNamed("arg2", 2).AddNamed("arg1", "foo")); Assert.AreEqual(arg1, component.Arg1); Assert.AreEqual(arg2, component.Arg2); } @@ -207,17 +192,4 @@ public void Should_resolve_component_when_no_parameters_passed_from_call_site() Kernel.Resolve()); } } - - public class ReadOnlyDictionary : Dictionary, IDictionary - { - public bool IsReadOnly - { - get { return true; } - } - - public new void Add(object key, object value) - { - throw new NotSupportedException(); - } - } } \ No newline at end of file diff --git a/src/Castle.Windsor.Tests/Registration/UsingFactoryMethodTestCase.cs b/src/Castle.Windsor.Tests/Registration/UsingFactoryMethodTestCase.cs index 3b67260206..89d344d464 100644 --- a/src/Castle.Windsor.Tests/Registration/UsingFactoryMethodTestCase.cs +++ b/src/Castle.Windsor.Tests/Registration/UsingFactoryMethodTestCase.cs @@ -171,7 +171,7 @@ public void Can_properly_resolve_component_from_UsingFactoryMethod_with_kernel_w new AbstractCarProviderFactory() .Create(k.Resolve(ctx.AdditionalArguments))) ); - var carProvider = Kernel.Resolve(new Arguments().Insert("FiscalStability", FiscalStability.MrMoneyBags)); + var carProvider = Kernel.Resolve(new Arguments().AddNamed("FiscalStability", FiscalStability.MrMoneyBags)); Assert.IsInstanceOf(carProvider); } diff --git a/src/Castle.Windsor.Tests/ResolveAllTestCase.cs b/src/Castle.Windsor.Tests/ResolveAllTestCase.cs index c7e367635f..253e7f83e8 100644 --- a/src/Castle.Windsor.Tests/ResolveAllTestCase.cs +++ b/src/Castle.Windsor.Tests/ResolveAllTestCase.cs @@ -14,6 +14,12 @@ namespace CastleTests { + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Linq; + + using Castle.MicroKernel; using Castle.MicroKernel.Handlers; using Castle.MicroKernel.Registration; diff --git a/src/Castle.Windsor.Tests/ResolveArgumentsTestCase.cs b/src/Castle.Windsor.Tests/ResolveArgumentsTestCase.cs new file mode 100644 index 0000000000..2bf9601774 --- /dev/null +++ b/src/Castle.Windsor.Tests/ResolveArgumentsTestCase.cs @@ -0,0 +1,204 @@ +// Copyright 2004-2018 Castle Project - http://www.castleproject.org/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace CastleTests +{ + using System; + using System.Collections.Generic; + + using Castle.MicroKernel; + using Castle.MicroKernel.Registration; + using Castle.MicroKernel.Resolvers.SpecializedResolvers; + using Castle.Windsor; + using NUnit.Framework; + + [TestFixture] + public class ResolveArgumentsTestCase : AbstractContainerTestCase + { + [SetUp] + public void SetUp() + { + Container.Kernel.Resolver.AddSubResolver(new ListResolver(Container.Kernel)); + Container.Register(Component.For()); + Container.Register(Component.For().ImplementedBy()); + Container.Register(Component.For().ImplementedBy()); + } + + [Test] + public void Can_Resolve_using_Arguments_as_Properties() + { + Assert.DoesNotThrow(() => Container.Resolve(Arguments.FromProperties(new { Dependency = new Dependency() }))); + } + + [Test] + public void Can_ResolveAll_using_Arguments_as_Properties() + { + Assert.DoesNotThrow(() => Container.ResolveAll(Arguments.FromProperties(new { Dependency = new Dependency() }))); + } + + [Test] + public void Can_Resolve_using_Type_and_Arguments_as_Properties() + { + Assert.DoesNotThrow(() => Container.Resolve(typeof(Service), Arguments.FromProperties(new { Dependency = new Dependency() }))); + } + + [Test] + public void Can_ResolveAll_using_Type_and_Arguments_as_Properties() + { + Assert.DoesNotThrow(() => Container.ResolveAll(typeof(IDependencyWithManyImplementations), Arguments.FromProperties(new { Dependency = new Dependency() }))); + } + + [Test] + public void Can_Resolve_using_Arguments_as_Dictionary() + { + var dictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(Arguments.FromNamed(dictionary))); + } + + [Test] + public void Can_ResolveAll_using_Arguments_as_Dictionary() + { + var dictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(Arguments.FromNamed(dictionary))); + } + + [Test] + public void Can_Resolve_using_Type_and_Arguments_as_Dictionary() + { + var dictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(typeof(Service), Arguments.FromNamed(dictionary))); + } + + [Test] + public void Can_ResolveAll_using_Type_and_Arguments_as_Dictionary() + { + var dictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(typeof(IDependencyWithManyImplementations), new Arguments().AddNamed(dictionary))); + } + + [Test] + public void Can_Resolve_using_Arguments_as_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(new Arguments().AddNamed(readOnlyDictionary))); + } + + [Test] + public void Can_ResolveAll_using_Arguments_as_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(new Arguments().AddNamed(readOnlyDictionary))); + } + + [Test] + public void Can_Resolve_using_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(readOnlyDictionary)); + } + + [Test] + public void Can_ResolveAll_using_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(readOnlyDictionary)); + } + + [Test] + public void Can_Resolve_using_Type_and_Arguments_as_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(typeof(Service), new Arguments().AddNamed(readOnlyDictionary))); + } + + [Test] + public void Can_ResolveAll_using_Type_and_Arguments_as_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(typeof(IDependencyWithManyImplementations), new Arguments().AddNamed(readOnlyDictionary))); + } + + [Test] + public void Can_Resolve_Type_and_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.Resolve(typeof(Service), readOnlyDictionary)); + } + + [Test] + public void Can_ResolveAll_Type_and_ReadOnlyDictionary() + { + IReadOnlyDictionary readOnlyDictionary = new Dictionary { { "dependency", new Dependency() } }; + Assert.DoesNotThrow(() => Container.ResolveAll(typeof(IDependencyWithManyImplementations), readOnlyDictionary)); + } + + [Test] + public void Can_Resolve_using_Arguments_as_TypedComponents() + { + Assert.DoesNotThrow(() => Container.Resolve(new Arguments().AddTyped(new Dependency()))); + } + + [Test] + public void Can_ResolveAll_using_Arguments_as_TypedComponents() + { + Assert.DoesNotThrow(() => Container.ResolveAll(new Arguments().AddTyped(new Dependency()))); + } + + [Test] + public void Can_Resolve_using_Type_and_Arguments_as_TypedComponents() + { + Assert.DoesNotThrow(() => Container.Resolve(typeof(Service), new Arguments().AddTyped(new Dependency()))); + } + + [Test] + public void Can_ResolveAll_using_Type_and_Arguments_as_TypedComponents() + { + Assert.DoesNotThrow(() => Container.Resolve(typeof(IDependencyWithManyImplementations), new Arguments().AddTyped(new Dependency()))); + } + + private class Dependency { } + + private class Service + { + private readonly Dependency dependency; + + public Service(Dependency dependency) + { + this.dependency = dependency ?? throw new ArgumentNullException(nameof(dependency)); + } + } + + private interface IDependencyWithManyImplementations { } + + private class DependencyImplementationA : IDependencyWithManyImplementations + { + private readonly Dependency dependency; + + public DependencyImplementationA(Dependency dependency) + { + this.dependency = dependency ?? throw new ArgumentNullException(nameof(dependency)); + } + } + + private class DependencyImplementationB : IDependencyWithManyImplementations + { + private readonly Dependency dependency; + + public DependencyImplementationB(Dependency dependency) + { + this.dependency = dependency ?? throw new ArgumentNullException(nameof(dependency)); + } + } + } +} \ No newline at end of file diff --git a/src/Castle.Windsor.Tests/RuntimeParametersTestCase.cs b/src/Castle.Windsor.Tests/RuntimeParametersTestCase.cs index 95a854ba87..5a25eca1db 100644 --- a/src/Castle.Windsor.Tests/RuntimeParametersTestCase.cs +++ b/src/Castle.Windsor.Tests/RuntimeParametersTestCase.cs @@ -21,6 +21,7 @@ namespace Castle.MicroKernel.Tests using Castle.MicroKernel.Registration; using Castle.MicroKernel.Resolvers; using Castle.MicroKernel.Tests.RuntimeParameters; + using Castle.Windsor; using CastleTests; @@ -60,7 +61,7 @@ public void Missing_service_is_correctly_detected() Container.Register(Component.For().Named("compa"), Component.For().Named("compb")); TestDelegate act = () => - Container.Resolve(new Arguments().Insert("myArgument", 123)); + Container.Resolve(new Arguments().AddNamed("myArgument", 123)); var exception = Assert.Throws(act); Assert.AreEqual( @@ -78,7 +79,7 @@ public void Parameter_takes_precedence_over_registered_service() Component.For().Instance(new CompC(0))); var c2 = new CompC(42); - var args = new Arguments(new object[] { c2 }); + var args = new Arguments().AddTyped(c2); var b = Container.Resolve(args); Assert.AreSame(c2, b.Compc); diff --git a/src/Castle.Windsor.Tests/TransientMultiConstructorTestCase.cs b/src/Castle.Windsor.Tests/TransientMultiConstructorTestCase.cs index 9b48319d61..477ab1403d 100644 --- a/src/Castle.Windsor.Tests/TransientMultiConstructorTestCase.cs +++ b/src/Castle.Windsor.Tests/TransientMultiConstructorTestCase.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel.Tests { using System; - using System.Collections.Generic; using Castle.Core; using Castle.MicroKernel.Registration; @@ -29,16 +28,16 @@ public class TransientMultiConstructorTestCase public void TransientMultiConstructorTest() { DefaultKernel container = new DefaultKernel(); - ((IKernel)container).Register(Component.For(typeof(FooBar)).Named("FooBar")); + ((IKernel)container).Register(Component.For(typeof(AnyClass)).Named("AnyClass")); - var arguments1 = new Dictionary(); + var arguments1 = new Arguments(); arguments1.Add("integer", 1); - var arguments2 = new Dictionary(); + var arguments2 = new Arguments(); arguments2.Add("datetime", DateTime.Now.AddDays(1)); - object a = container.Resolve(typeof(FooBar), arguments1); - object b = container.Resolve(typeof(FooBar), arguments2); + object a = container.Resolve(typeof(AnyClass), arguments1); + object b = container.Resolve(typeof(AnyClass), arguments2); Assert.AreNotSame(a, b, "A should not be B"); } @@ -47,38 +46,38 @@ public void TransientMultiConstructorTest() public void TransientMultipleConstructorNonValueTypeTest() { DefaultKernel container = new DefaultKernel(); - ((IKernel)container).Register(Component.For(typeof(FooBarNonValue)).Named("FooBar")); - Tester1 bla1 = new Tester1("FOOBAR"); - Tester2 bla2 = new Tester2(666); + ((IKernel)container).Register(Component.For(typeof(AnyClassWithReference)).Named("AnyClass")); + Tester1 one = new Tester1("AnyString"); + Tester2 two = new Tester2(1); - var arguments1 = new Dictionary(); - arguments1.Add("test1", bla1); + var arguments1 = new Arguments(); + arguments1.Add("test1", one); - var arguments2 = new Dictionary(); - arguments2.Add("test2", bla2); + var arguments2 = new Arguments(); + arguments2.Add("test2", two); - object a = container.Resolve(typeof(FooBarNonValue), arguments1); - object b = container.Resolve(typeof(FooBarNonValue), arguments2); + object a = container.Resolve(typeof(AnyClassWithReference), arguments1); + object b = container.Resolve(typeof(AnyClassWithReference), arguments2); Assert.AreNotSame(a, b, "A should not be B"); // multi resolve test - a = container.Resolve(typeof(FooBarNonValue), arguments1); - b = container.Resolve(typeof(FooBarNonValue), arguments2); + a = container.Resolve(typeof(AnyClassWithReference), arguments1); + b = container.Resolve(typeof(AnyClassWithReference), arguments2); Assert.AreNotSame(a, b, "A should not be B"); } } [Transient] - public class FooBar + public class AnyClass { - public FooBar(int integer) + public AnyClass(int integer) { } - public FooBar(DateTime datetime) + public AnyClass(DateTime datetime) { } } @@ -104,13 +103,13 @@ public Tester2(int foo) } [Transient] - public class FooBarNonValue + public class AnyClassWithReference { - public FooBarNonValue(Tester1 test1) + public AnyClassWithReference(Tester1 test1) { } - public FooBarNonValue(Tester2 test2) + public AnyClassWithReference(Tester2 test2) { } } diff --git a/src/Castle.Windsor.Tests/TypedParametersTestCase.cs b/src/Castle.Windsor.Tests/TypedParametersTestCase.cs index 2afc08c0c1..0c414e1740 100644 --- a/src/Castle.Windsor.Tests/TypedParametersTestCase.cs +++ b/src/Castle.Windsor.Tests/TypedParametersTestCase.cs @@ -14,9 +14,6 @@ namespace CastleTests { - using System; - using System.Collections.Generic; - using Castle.MicroKernel; using Castle.MicroKernel.Registration; using Castle.MicroKernel.SubSystems.Conversion; @@ -34,8 +31,7 @@ public class TypedParametersTestCase : AbstractContainerTestCase public void Can_mix_typed_arguments_with_named() { Kernel.Register(Component.For()); - var arguments = new Dictionary - { + var arguments = new Arguments { { "arg1", "foo" }, { typeof(int), 2 } }; @@ -50,8 +46,7 @@ public void Can_mix_typed_arguments_with_named() public void Can_named_arguments_take_precedense_over_typed() { Kernel.Register(Component.For()); - var arguments = new Dictionary - { + var arguments = new Arguments { { "arg1", "named" }, { typeof(string), "typed" }, { typeof(int), 2 } @@ -67,8 +62,7 @@ public void Can_named_arguments_take_precedense_over_typed() public void Can_resolve_component_with_typed_arguments() { Kernel.Register(Component.For()); - var arguments = new Dictionary - { + var arguments = new Arguments { { typeof(string), "foo" }, { typeof(int), 2 } }; @@ -82,7 +76,7 @@ public void Can_resolve_component_with_typed_arguments() [Test] public void Typed_arguments_work_for_DynamicParameters() { - Kernel.Register(Component.For().DynamicParameters((k, d) => d.InsertTyped("typed").InsertTyped(2))); + Kernel.Register(Component.For().DynamicParameters((k, d) => d.AddTyped("typed").AddTyped(2))); var item = Kernel.Resolve(); @@ -93,9 +87,8 @@ public void Typed_arguments_work_for_DynamicParameters() [Test] public void Typed_arguments_work_for_DynamicParameters_mixed() { - Kernel.Register(Component.For().DynamicParameters((k, d) => d.InsertTyped("typed"))); - var arguments = new Dictionary - { + Kernel.Register(Component.For().DynamicParameters((k, d) => d.AddTyped("typed"))); + var arguments = new Arguments { { typeof(int), 2 } }; var item = Kernel.Resolve(arguments); @@ -110,20 +103,20 @@ public void Typed_arguments_work_for_DynamicParameters_mixed2() Kernel.Register(Component.For()); Assert.Throws(() => { - Kernel.Resolve(new Arguments(new Dictionary - { + Kernel.Resolve(new Arguments { { typeof(int), "not an int" }, { typeof(string), "a string" } - })); - }); + }); + }); } [Test] public void Typed_arguments_work_for_InLine_Parameters() { Kernel.Register(Component.For() - .DependsOn(Property.ForKey().Eq("typed"), - Property.ForKey().Eq(2))); + .DependsOn( + Property.ForKey().Eq("typed"), + Property.ForKey().Eq(2))); var item = Kernel.Resolve(); @@ -136,8 +129,7 @@ public void Typed_arguments_work_for_ServiceOverrides() { Kernel.Register(Component.For().ImplementedBy().Named("default")); Kernel.Register(Component.For().ImplementedBy().Named("non-default")); - Kernel.Register( - Component.For().DependsOn(ServiceOverride.ForKey().Eq("non-default"))); + Kernel.Register(Component.For().DependsOn(ServiceOverride.ForKey().Eq("non-default"))); var item = Kernel.Resolve(); @@ -147,9 +139,10 @@ public void Typed_arguments_work_for_ServiceOverrides() [Test] public void Typed_arguments_work_for_closed_generic_ServiceOverrides() { - Kernel.Register(Component.For>().ImplementedBy>().Named("default"), - Component.For>().ImplementedBy>().Named("non-default"), - Component.For>().DependsOn(ServiceOverride.ForKey>().Eq("non-default"))); + Kernel.Register( + Component.For>().ImplementedBy>().Named("default"), + Component.For>().ImplementedBy>().Named("non-default"), + Component.For>().DependsOn(ServiceOverride.ForKey>().Eq("non-default"))); var item = Kernel.Resolve>(); @@ -162,7 +155,7 @@ public void Typed_arguments_work_for_open_generic_ServiceOverrides_closed_servic Kernel.Register(Component.For(typeof(IGeneric<>)).ImplementedBy(typeof(GenericImpl1<>)).Named("default")); Kernel.Register(Component.For(typeof(IGeneric<>)).ImplementedBy(typeof(GenericImpl2<>)).Named("non-default")); Kernel.Register(Component.For(typeof(UsesIGeneric<>)) - .DependsOn(ServiceOverride.ForKey(typeof(IGeneric)).Eq("non-default"))); + .DependsOn(ServiceOverride.ForKey(typeof(IGeneric)).Eq("non-default"))); var item = Kernel.Resolve>(); diff --git a/src/Castle.Windsor/Core/ComponentModel.cs b/src/Castle.Windsor/Core/ComponentModel.cs index 20cd9a0808..7a43d883ff 100644 --- a/src/Castle.Windsor/Core/ComponentModel.cs +++ b/src/Castle.Windsor/Core/ComponentModel.cs @@ -46,7 +46,7 @@ public sealed class ComponentModel : GraphNode [NonSerialized] [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private IDictionary customDependencies; + private Arguments customDependencies; /// /// Dependencies the kernel must resolve @@ -56,7 +56,7 @@ public sealed class ComponentModel : GraphNode [NonSerialized] [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private IDictionary extendedProperties; + private Arguments extendedProperties; /// /// Interceptors associated @@ -79,7 +79,7 @@ public sealed class ComponentModel : GraphNode /// /// Constructs a ComponentModel /// - public ComponentModel(ComponentName name, ICollection services, Type implementation, IDictionary extendedProperties) + public ComponentModel(ComponentName name, ICollection services, Type implementation, Arguments extendedProperties) { componentName = Must.NotBeNull(name, "name"); Implementation = Must.NotBeNull(implementation, "implementation"); @@ -128,7 +128,7 @@ public ConstructorCandidateCollection Constructors /// /// The custom dependencies. [DebuggerDisplay("Count = {customDependencies.Count}")] - public IDictionary CustomDependencies + public Arguments CustomDependencies { get { @@ -173,7 +173,7 @@ public DependencyModelCollection Dependencies /// /// The extended properties. [DebuggerDisplay("Count = {extendedProperties.Count}")] - public IDictionary ExtendedProperties + public Arguments ExtendedProperties { get { diff --git a/src/Castle.Windsor/Core/Internal/Constants.cs b/src/Castle.Windsor/Core/Internal/Constants.cs index a62800cf82..b16ef3684f 100644 --- a/src/Castle.Windsor/Core/Internal/Constants.cs +++ b/src/Castle.Windsor/Core/Internal/Constants.cs @@ -14,34 +14,32 @@ namespace Castle.Core.Internal { - public abstract class Constants + public static class Constants { private const string defaultComponentForServiceFilter = "castle.default-component-for-service-filter"; private const string fallbackComponentForServiceFilter = "castle.fallback-component-for-service-filter"; private const string genericImplementationMatchingStrategy = "castle.generic-matching-strategy"; private const string genericServiceStrategy = "castle.generic-service-strategy"; - private const string helpLink = @"groups.google.com/group/castle-project-users"; private const string propertyFilters = "castle.property-filters"; private const string scopeAccessorType = "castle.scope-accessor-type"; private const string scopeRootSelector = "castle.scope-root"; - public static object DefaultComponentForServiceFilter + public static string DefaultComponentForServiceFilter { get { return defaultComponentForServiceFilter; } } public static string ExceptionHelpLink { - get { return helpLink; } + get { return "http://www.castleproject.org/"; } } - public static object FallbackComponentForServiceFilter + public static string FallbackComponentForServiceFilter { get { return fallbackComponentForServiceFilter; } } - public static string GenericImplementationMatchingStrategy { get { return genericImplementationMatchingStrategy; } @@ -52,17 +50,17 @@ public static string GenericServiceStrategy get { return genericServiceStrategy; } } - public static object PropertyFilters + public static string PropertyFilters { get { return propertyFilters; } } - public static object ScopeAccessorType + public static string ScopeAccessorType { get { return scopeAccessorType; } } - public static object ScopeRootSelector + public static string ScopeRootSelector { get { return scopeRootSelector; } } diff --git a/src/Castle.Windsor/Facilities/TypedFactory/DefaultDelegateComponentSelector.cs b/src/Castle.Windsor/Facilities/TypedFactory/DefaultDelegateComponentSelector.cs index 2262c1c72e..e1a3927357 100644 --- a/src/Castle.Windsor/Facilities/TypedFactory/DefaultDelegateComponentSelector.cs +++ b/src/Castle.Windsor/Facilities/TypedFactory/DefaultDelegateComponentSelector.cs @@ -15,7 +15,6 @@ namespace Castle.Facilities.TypedFactory { using System; - using System.Collections; using System.Reflection; using Castle.Core; @@ -24,7 +23,7 @@ namespace Castle.Facilities.TypedFactory [Singleton] public class DefaultDelegateComponentSelector : DefaultTypedFactoryComponentSelector { - protected override IDictionary GetArguments(MethodInfo method, object[] arguments) + protected override Arguments GetArguments(MethodInfo method, object[] arguments) { var parameters = method.GetParameters(); var arg = new Arguments(); diff --git a/src/Castle.Windsor/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs b/src/Castle.Windsor/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs index 12fd515a11..222ae9c5f4 100644 --- a/src/Castle.Windsor/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs +++ b/src/Castle.Windsor/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs @@ -71,7 +71,7 @@ public Func SelectComponent(MethodInfo protected virtual Func BuildFactoryComponent(MethodInfo method, string componentName, Type componentType, - IDictionary additionalArguments) + Arguments additionalArguments) { var itemType = componentType.GetCompatibleArrayItemType(); if (itemType == null) @@ -92,7 +92,7 @@ protected virtual Func BuildFactoryComp /// /// /// - protected virtual IDictionary GetArguments(MethodInfo method, object[] arguments) + protected virtual Arguments GetArguments(MethodInfo method, object[] arguments) { if (arguments == null) { diff --git a/src/Castle.Windsor/Facilities/TypedFactory/Internal/DelegateFactory.cs b/src/Castle.Windsor/Facilities/TypedFactory/Internal/DelegateFactory.cs index 059cd3a2ae..a1fbc77014 100644 --- a/src/Castle.Windsor/Facilities/TypedFactory/Internal/DelegateFactory.cs +++ b/src/Castle.Windsor/Facilities/TypedFactory/Internal/DelegateFactory.cs @@ -15,19 +15,19 @@ namespace Castle.Facilities.TypedFactory.Internal { using System; - using System.Collections; using System.Diagnostics; using System.Reflection; using Castle.Core; using Castle.Core.Internal; + using Castle.MicroKernel; using Castle.MicroKernel.Registration; using Castle.MicroKernel.Resolvers; [Singleton] public class DelegateFactory : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { if (service == null) { @@ -55,12 +55,11 @@ public IRegistration Load(string name, Type service, IDictionary arguments) .LifeStyle.Transient .Interceptors(new InterceptorReference(TypedFactoryFacility.InterceptorKey)).Last .Activator() - .DynamicParameters((k, d) => - { - var selector = k.Resolve(TypedFactoryFacility.DefaultDelegateSelectorKey); - d.InsertTyped(selector); - return k2 => k2.ReleaseComponent(selector); - }) + .DynamicParameters((k, args) => { + var selector = k.Resolve(TypedFactoryFacility.DefaultDelegateSelectorKey); + args.AddTyped(selector); + return k2 => k2.ReleaseComponent(selector); + }) .AddAttributeDescriptor(TypedFactoryFacility.IsFactoryKey, bool.TrueString); } diff --git a/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryComponentResolver.cs b/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryComponentResolver.cs index 249449bba4..4bbb779959 100644 --- a/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryComponentResolver.cs +++ b/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryComponentResolver.cs @@ -15,7 +15,6 @@ namespace Castle.Facilities.TypedFactory { using System; - using System.Collections; using Castle.MicroKernel; @@ -24,13 +23,13 @@ namespace Castle.Facilities.TypedFactory /// public class TypedFactoryComponentResolver { - protected readonly IDictionary additionalArguments; + protected readonly Arguments additionalArguments; protected readonly string componentName; protected readonly Type componentType; protected readonly bool fallbackToResolveByTypeIfNameNotFound; private readonly Type actualSelectorType; - public TypedFactoryComponentResolver(string componentName, Type componentType, IDictionary additionalArguments, + public TypedFactoryComponentResolver(string componentName, Type componentType, Arguments additionalArguments, bool fallbackToResolveByTypeIfNameNotFound, Type actualSelectorType) { if (string.IsNullOrEmpty(componentName) && componentType == null) diff --git a/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs b/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs index 388d645d89..6558104126 100644 --- a/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs +++ b/src/Castle.Windsor/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs @@ -171,10 +171,9 @@ private static ComponentRegistration AttachConfiguration( return componentRegistration .AddDescriptor(new ReferenceDependencyDescriptor(selectorReference)) - .DynamicParameters((k, c, d) => - { - var selector = selectorReference.Resolve(k, c); - d.InsertTyped(selector); + .DynamicParameters((k, context, args) => { + var selector = selectorReference.Resolve(k, context); + args.AddTyped(selector); return k2 => k2.ReleaseComponent(selector); }) .AddAttributeDescriptor(TypedFactoryFacility.IsFactoryKey, bool.TrueString); diff --git a/src/Castle.Windsor/MicroKernel/Arguments.cs b/src/Castle.Windsor/MicroKernel/Arguments.cs index 2ea9084f4d..f5feb29607 100644 --- a/src/Castle.Windsor/MicroKernel/Arguments.cs +++ b/src/Castle.Windsor/MicroKernel/Arguments.cs @@ -1,4 +1,4 @@ -// Copyright 2004-2011 Castle Project - http://www.castleproject.org/ +// Copyright 2004-2018 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,208 +19,223 @@ namespace Castle.MicroKernel using System.Collections.Generic; using Castle.Core; - using Castle.MicroKernel.Context; + using Castle.Windsor; /// - /// Represents collection of arguments used when resolving a component. + /// Represents a collection of named and typed arguments used for dependencies resolved via + /// See: https://github.com/castleproject/Windsor/blob/master/docs/arguments.md /// - public class Arguments : IDictionary + public sealed class Arguments + : IEnumerable> // Required for collection initializers { - protected IDictionary arguments; + private static readonly ArgumentsComparer Comparer = new ArgumentsComparer(); - public Arguments(object namedArgumentsAsAnonymousType, params IArgumentsComparer[] customComparers) - : this(new ReflectionBasedDictionaryAdapter(namedArgumentsAsAnonymousType), customComparers) - { - } + private readonly Dictionary dictionary; - public Arguments(IDictionary values, params IArgumentsComparer[] customComparers) - : this(customComparers) + /// + /// Initializes a new instance of the class that is empty. + /// + public Arguments() { - foreach (DictionaryEntry entry in values) - { - Add(entry.Key, entry.Value); - } + dictionary = new Dictionary(Comparer); } - public Arguments(object[] typedArguments, params IArgumentsComparer[] customComparers) - : this(customComparers) + /// + /// Initializes a new instance of the class that contains elements copied from the specified . + /// + public Arguments(Arguments arguments) { - foreach (var @object in typedArguments) - { - if (@object == null) - { - throw new ArgumentNullException("typedArguments", - "Given array has null values. Only non-null values can be used as arguments."); - } - - Add(@object.GetType(), @object); - } + dictionary = new Dictionary(arguments.dictionary, Comparer); } - public Arguments(params IArgumentsComparer[] customComparers) - { - if (customComparers == null || customComparers.Length == 0) - { - arguments = new Dictionary(new ArgumentsComparer()); - } - else - { - arguments = new Dictionary(new ArgumentsComparerExtended(customComparers)); - } - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IEnumerator> GetEnumerator() => dictionary.GetEnumerator(); + public int Count => dictionary.Count; - public int Count + public void Add(object key, object value) { - get { return arguments.Count; } + CheckKeyType(key); + dictionary.Add(key, value); } - public object this[object key] + public bool Contains(object key) { - get { return arguments[key]; } - set { arguments[key] = value; } + CheckKeyType(key); + return dictionary.ContainsKey(key); } - public ICollection Keys + public void Remove(object key) { - get { return arguments.Keys; } + CheckKeyType(key); + dictionary.Remove(key); } - public ICollection Values + public object this[object key] { - get { return arguments.Values; } + get + { + CheckKeyType(key); + if (dictionary.TryGetValue(key, out object value)) + { + return value; + } + return null; + } + set + { + CheckKeyType(key); + dictionary[key] = value; + } } - bool ICollection.IsSynchronized + /// + /// Adds a collection of named and/or typed arguments. + /// + public Arguments Add(IEnumerable> arguments) { - get { return arguments.IsSynchronized; } + foreach (KeyValuePair item in arguments) + { + Add(item.Key, item.Value); + } + return this; } - object ICollection.SyncRoot + /// + /// Adds a named argument. + /// + public Arguments AddNamed(string key, object value) { - get { return arguments.SyncRoot; } + Add(key, value); + return this; } - bool IDictionary.IsFixedSize + /// + /// Adds a collection of named arguments, implements this interface. + /// + public Arguments AddNamed(IEnumerable> arguments) { - get { return arguments.IsFixedSize; } + foreach (var item in arguments) + { + AddNamed(item.Key, item.Value); + } + return this; } - bool IDictionary.IsReadOnly + /// + /// Adds a collection of named arguments from public properties of a standard or anonymous type. + /// + public Arguments AddProperties(object instance) { - get { return arguments.IsReadOnly; } + foreach (DictionaryEntry item in new ReflectionBasedDictionaryAdapter(instance)) + { + Add(item.Key, item.Value); + } + return this; } - public void Add(object key, object value) + /// + /// Adds a typed argument. + /// + public Arguments AddTyped(Type key, object value) { - arguments.Add(key, value); + Add(key, value); + return this; } - public void Clear() + /// + /// Adds a typed argument. + /// + public Arguments AddTyped(TDependencyType value) { - arguments.Clear(); + AddTyped(typeof(TDependencyType), value); + return this; } - public bool Contains(object key) + /// + /// Adds a collection of typed arguments. + /// + public Arguments AddTyped(IEnumerable arguments) { - return arguments.Contains(key); + foreach (object item in arguments) + { + AddTyped(item.GetType(), item); + } + return this; } - public IDictionaryEnumerator GetEnumerator() + /// + /// Adds a collection of typed arguments. + /// + public Arguments AddTyped(params object[] arguments) { - return arguments.GetEnumerator(); + foreach (object item in arguments) + { + AddTyped(item.GetType(), item); + } + return this; } - public void Remove(object key) + /// + /// Initializes a new instance of the class and adds a collection of named arguments, + /// implements this interface. + /// + public static Arguments FromNamed(IEnumerable> arguments) { - arguments.Remove(key); + return new Arguments().AddNamed(arguments); } - public Arguments Clone() + /// + /// Initializes a new instance of the class and adds a collection of named arguments + /// from public properties of a standard or anonymous type. + /// + public static Arguments FromProperties(object instance) { - var dictionary = arguments as Dictionary; - if (dictionary != null) - { - var comparerExtended = dictionary.Comparer as ArgumentsComparerExtended; - if (comparerExtended != null) - { - return new Arguments(arguments, comparerExtended.CustomComparers); - } - } - - return new Arguments(arguments); + return new Arguments().AddProperties(instance); } - void ICollection.CopyTo(Array array, int index) + /// + /// Initializes a new instance of the class and adds a collection of typed arguments, + /// implements this interface. + /// + public static Arguments FromTyped(IEnumerable> arguments) { - arguments.CopyTo(array, index); + return new Arguments().AddTyped(arguments); } - IEnumerator IEnumerable.GetEnumerator() + /// + /// Initializes a new instance of the class and adds a collection of typed arguments. + /// + public static Arguments FromTyped(IEnumerable arguments) { - return GetEnumerator(); + return new Arguments().AddTyped(arguments); } - private class ArgumentsComparer : IEqualityComparer + private void CheckKeyType(object key) { - public new virtual bool Equals(object x, object y) - { - var a = x as string; - if (a != null) - { - return StringComparer.OrdinalIgnoreCase.Equals(a, y as string); - } - return Object.Equals(x, y); - } - - public virtual int GetHashCode(object obj) + if (!(key is string) && !(key is Type)) { - var str = obj as string; - if (str != null) - { - return StringComparer.OrdinalIgnoreCase.GetHashCode(str); - } - return obj.GetHashCode(); + throw new ArgumentException($"The argument '{key}' should be of type string or System.Type."); } } - private class ArgumentsComparerExtended : ArgumentsComparer + private sealed class ArgumentsComparer : IEqualityComparer { - private readonly List nestedComparers = new List(); - - public ArgumentsComparerExtended(IEnumerable customStores) - { - nestedComparers = new List(customStores); - } - - public IArgumentsComparer[] CustomComparers - { - get { return nestedComparers.ToArray(); } - } - - public override bool Equals(object x, object y) + public new bool Equals(object x, object y) { - foreach (var store in nestedComparers) + if (x is string a) { - bool areEqual; - if (store.RunEqualityComparison(x, y, out areEqual)) - { - return areEqual; - } + return StringComparer.OrdinalIgnoreCase.Equals(a, y as string); } - return base.Equals(x, y); + return object.Equals(x, y); } - public override int GetHashCode(object obj) + public int GetHashCode(object obj) { - foreach (var store in nestedComparers) + if (obj is string str) { - int hashCode; - if (store.RunHasCodeCalculation(obj, out hashCode)) - { - return hashCode; - } + return StringComparer.OrdinalIgnoreCase.GetHashCode(str); } - return base.GetHashCode(obj); + return obj.GetHashCode(); } } } diff --git a/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs b/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs index e642d85733..02453d7838 100644 --- a/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs +++ b/src/Castle.Windsor/MicroKernel/ComponentActivator/DefaultComponentActivator.cs @@ -37,6 +37,8 @@ namespace Castle.MicroKernel.ComponentActivator [Serializable] public class DefaultComponentActivator : AbstractComponentActivator { + internal const string InstanceStash = "castle.component-activator-instance"; + #if FEATURE_REMOTING private readonly bool useFastCreateInstance; #endif @@ -59,7 +61,7 @@ public DefaultComponentActivator(ComponentModel model, IKernelInternal kernel, C protected override object InternalCreate(CreationContext context) { var instance = Instantiate(context); - context.SetContextualProperty(this, instance); + context.SetContextualProperty(InstanceStash, instance); SetUpProperties(instance, context); diff --git a/src/Castle.Windsor/MicroKernel/Context/CreationContext.cs b/src/Castle.Windsor/MicroKernel/Context/CreationContext.cs index 57dd039fea..f1d73e8fe7 100644 --- a/src/Castle.Windsor/MicroKernel/Context/CreationContext.cs +++ b/src/Castle.Windsor/MicroKernel/Context/CreationContext.cs @@ -55,8 +55,8 @@ public class CreationContext : private readonly Type requestedType; private readonly Stack resolutionStack; - private IDictionary additionalArguments; - private IDictionary extendedProperties; + private Arguments additionalArguments; + private Arguments extendedProperties; private Type[] genericArguments; private bool isResolving = true; @@ -95,13 +95,13 @@ public CreationContext(Type requestedType, CreationContext parentContext, bool p /// The conversion manager. /// Parent context public CreationContext(IHandler handler, IReleasePolicy releasePolicy, Type requestedType, - IDictionary additionalArguments, ITypeConverter converter, + Arguments additionalArguments, ITypeConverter converter, CreationContext parent) { this.requestedType = requestedType; this.handler = handler; ReleasePolicy = releasePolicy; - this.additionalArguments = EnsureAdditionalArgumentsWriteable(additionalArguments); + this.additionalArguments = additionalArguments; this.converter = converter; if (parent != null) @@ -126,7 +126,7 @@ private CreationContext() resolutionStack = new Stack(4); } - public IDictionary AdditionalArguments + public Arguments AdditionalArguments { get { @@ -247,9 +247,7 @@ public object GetContextualProperty(object key) { return null; } - - var value = extendedProperties[key]; - return value; + return extendedProperties[key]; } /// @@ -351,25 +349,6 @@ private bool CanResolveByType(DependencyModel dependency) return CanResolve(dependency, additionalArguments[type]); } - private IDictionary EnsureAdditionalArgumentsWriteable(IDictionary dictionary) - { - // NOTE: this is actually here mostly to workaround the fact that ReflectionBasedDictionaryAdapter is read only - // we could make it writeable instead, but I'm not sure that would make sense. - // NOTE: As noted in IOC-ISSUE-190 that may lead to issues with custom IDictionary implementations - // We better just ignore not known implementations and if someone uses one, it's their problem to take that into - // account when dealing with DynamicParameters - if (dictionary == null) - { - return null; - } - - if (!(dictionary is ReflectionBasedDictionaryAdapter)) - { - return dictionary; - } - return new Arguments(dictionary); - } - private void ExitResolutionContext(Burden burden, bool trackContext) { handlerStack.Pop(); @@ -453,7 +432,7 @@ public class ResolutionContext : IDisposable private readonly bool requiresDecommission; private readonly bool trackContext; private Burden burden; - private IDictionary extendedProperties; + private Arguments extendedProperties; public ResolutionContext(CreationContext context, IHandler handler, bool requiresDecommission, bool trackContext) { diff --git a/src/Castle.Windsor/MicroKernel/DefaultKernel.cs b/src/Castle.Windsor/MicroKernel/DefaultKernel.cs index 4589bd74b8..ac0724d6e9 100644 --- a/src/Castle.Windsor/MicroKernel/DefaultKernel.cs +++ b/src/Castle.Windsor/MicroKernel/DefaultKernel.cs @@ -516,7 +516,7 @@ public virtual bool HasComponent(Type serviceType) /// Registers the components with the . The instances of are produced by fluent registration API. Most common entry points are /// method to register a single type or (recommended in most cases) . Let the Intellisense drive you through the /// fluent - /// API past those entry points. For details see the documentation at http://j.mp/WindsorApi + /// API past those entry points. /// /// /// kernel.Register(Component.For<IService>().ImplementedBy<DefaultService>().LifestyleTransient()); @@ -689,7 +689,7 @@ public virtual IComponentActivator CreateComponentActivator(ComponentModel model return activator; } - protected CreationContext CreateCreationContext(IHandler handler, Type requestedType, IDictionary additionalArguments, CreationContext parent, + protected CreationContext CreateCreationContext(IHandler handler, Type requestedType, Arguments additionalArguments, CreationContext parent, IReleasePolicy policy) { return new CreationContext(handler, policy, requestedType, additionalArguments, ConversionSubSystem, parent); @@ -734,12 +734,12 @@ protected virtual void RegisterSubSystems() new DefaultDiagnosticsSubSystem()); } - protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy) + protected object ResolveComponent(IHandler handler, Type service, Arguments additionalArguments, IReleasePolicy policy) { return ResolveComponent(handler, service, additionalArguments, policy, ignoreParentContext: false); } - private object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy, bool ignoreParentContext) + private object ResolveComponent(IHandler handler, Type service, Arguments additionalArguments, IReleasePolicy policy, bool ignoreParentContext) { Debug.Assert(handler != null, "handler != null"); var parent = currentCreationContext; @@ -835,7 +835,7 @@ private void UnsubscribeFromParentKernel() parentKernel.ComponentRegistered -= RaiseComponentRegistered; } - IHandler IKernelInternal.LoadHandlerByName(string name, Type service, IDictionary arguments) + IHandler IKernelInternal.LoadHandlerByName(string name, Type service, Arguments arguments) { if (name == null) { @@ -881,7 +881,7 @@ IHandler IKernelInternal.LoadHandlerByName(string name, Type service, IDictionar } } - IHandler IKernelInternal.LoadHandlerByType(string name, Type service, IDictionary arguments) + IHandler IKernelInternal.LoadHandlerByType(string name, Type service, Arguments arguments) { if (service == null) { diff --git a/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs b/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs index 2859888e74..0d14d31bda 100644 --- a/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs +++ b/src/Castle.Windsor/MicroKernel/DefaultKernel_Resolve.cs @@ -18,7 +18,6 @@ namespace Castle.MicroKernel using System.Collections; using System.Collections.Generic; - using Castle.Core; using Castle.MicroKernel.Handlers; public partial class DefaultKernel @@ -41,7 +40,7 @@ public virtual object Resolve(String key, Type service) /// /// /// - public virtual object Resolve(String key, Type service, IDictionary arguments) + public virtual object Resolve(string key, Type service, Arguments arguments) { return (this as IKernelInternal).Resolve(key, service, arguments, ReleasePolicy); } @@ -52,22 +51,11 @@ public virtual object Resolve(String key, Type service, IDictionary arguments) /// /// /// - public T Resolve(IDictionary arguments) + public T Resolve(Arguments arguments) { return (T)Resolve(typeof(T), arguments); } - /// - /// Returns the component instance by the service type - /// using dynamic arguments - /// - /// - /// - public T Resolve(object argumentsAsAnonymousType) - { - return (T)Resolve(typeof(T), new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns the component instance by the component key /// @@ -99,7 +87,7 @@ public T Resolve(String key) /// /// The Component instance /// - public T Resolve(String key, IDictionary arguments) + public T Resolve(string key, Arguments arguments) { return (T)(this as IKernelInternal).Resolve(key, typeof(T), arguments, ReleasePolicy); } @@ -119,23 +107,11 @@ public object Resolve(Type service) /// /// /// - public object Resolve(Type service, IDictionary arguments) + public object Resolve(Type service, Arguments arguments) { return (this as IKernelInternal).Resolve(service, arguments, ReleasePolicy); } - /// - /// Returns the component instance by the service type - /// using dynamic arguments - /// - /// - /// - /// - public object Resolve(Type service, object argumentsAsAnonymousType) - { - return Resolve(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns all the valid component instances by /// the service type @@ -152,45 +128,20 @@ public Array ResolveAll(Type service) /// /// The service type /// - /// Arguments to resolve the services + /// Arguments to resolve the services /// - public Array ResolveAll(Type service, IDictionary arguments) + public Array ResolveAll(Type service, Arguments arguments) { return (this as IKernelInternal).ResolveAll(service, arguments, ReleasePolicy); } - /// - /// Returns all the valid component instances by - /// the service type - /// - /// The service type - /// - /// Arguments to resolve the services - /// - public Array ResolveAll(Type service, object argumentsAsAnonymousType) - { - return (this as IKernelInternal).ResolveAll(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType), ReleasePolicy); - } - - /// - /// Returns component instances that implement TService - /// - /// - /// - /// - public TService[] ResolveAll(object argumentsAsAnonymousType) - { - return - (TService[])(this as IKernelInternal).ResolveAll(typeof(TService), new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType), ReleasePolicy); - } - /// /// Returns component instances that implement TService /// /// /// /// - public TService[] ResolveAll(IDictionary arguments) + public TService[] ResolveAll(Arguments arguments) { return (TService[])(this as IKernelInternal).ResolveAll(typeof(TService), arguments, ReleasePolicy); } @@ -213,7 +164,7 @@ public TService[] ResolveAll() /// /// /// - object IKernelInternal.Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy) + object IKernelInternal.Resolve(string key, Type service, Arguments arguments, IReleasePolicy policy) { var handler = (this as IKernelInternal).LoadHandlerByName(key, service, arguments); if (handler == null) @@ -224,7 +175,7 @@ object IKernelInternal.Resolve(String key, Type service, IDictionary arguments, return ResolveComponent(handler, service ?? typeof(object), arguments, policy); } - object IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy, bool ignoreParentContext) + object IKernelInternal.Resolve(Type service, Arguments arguments, IReleasePolicy policy, bool ignoreParentContext) { var handler = (this as IKernelInternal).LoadHandlerByType(null, service, arguments); if(handler == null) @@ -234,7 +185,7 @@ object IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePoli return ResolveComponent(handler, service, arguments, policy, ignoreParentContext); } - Array IKernelInternal.ResolveAll(Type service, IDictionary arguments, IReleasePolicy policy) + Array IKernelInternal.ResolveAll(Type service, Arguments arguments, IReleasePolicy policy) { var resolved = new List(); foreach (var handler in GetHandlers(service)) diff --git a/src/Castle.Windsor/MicroKernel/Handlers/DefaultGenericHandler.cs b/src/Castle.Windsor/MicroKernel/Handlers/DefaultGenericHandler.cs index 2f1fdd2e1e..f2f2995c48 100644 --- a/src/Castle.Windsor/MicroKernel/Handlers/DefaultGenericHandler.cs +++ b/src/Castle.Windsor/MicroKernel/Handlers/DefaultGenericHandler.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel.Handlers { using System; - using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; @@ -265,7 +264,7 @@ private void CloneParentProperties(ComponentModel newModel) if (ComponentModel.HasCustomDependencies) { var dependencies = newModel.CustomDependencies; - foreach (DictionaryEntry dependency in ComponentModel.CustomDependencies) + foreach (var dependency in ComponentModel.CustomDependencies) { dependencies.Add(dependency.Key, dependency.Value); } @@ -366,19 +365,12 @@ private Type GetClosedImplementationType(CreationContext context, bool instanceR } } - private IDictionary GetExtendedProperties() + private Arguments GetExtendedProperties() { var extendedProperties = ComponentModel.ExtendedProperties; if (extendedProperties != null && extendedProperties.Count > 0) { - if (extendedProperties is Arguments) - { - extendedProperties = ((Arguments)extendedProperties).Clone(); - } - else - { - extendedProperties = new Arguments(extendedProperties); - } + extendedProperties = new Arguments(extendedProperties); } return extendedProperties; } diff --git a/src/Castle.Windsor/MicroKernel/IComponentModelBuilder.cs b/src/Castle.Windsor/MicroKernel/IComponentModelBuilder.cs index 0133eae18e..7cd14c8aa0 100644 --- a/src/Castle.Windsor/MicroKernel/IComponentModelBuilder.cs +++ b/src/Castle.Windsor/MicroKernel/IComponentModelBuilder.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel { using System; - using System.Collections; using Castle.Core; using Castle.MicroKernel.ModelBuilder; @@ -42,12 +41,7 @@ public interface IComponentModelBuilder /// Constructs a new ComponentModel by invoking /// the registered contributors. /// - /// - /// - /// - /// - /// - ComponentModel BuildModel(ComponentName name, Type[] services, Type classType, IDictionary extendedProperties); + ComponentModel BuildModel(ComponentName name, Type[] services, Type classType, Arguments extendedProperties); ComponentModel BuildModel(IComponentModelDescriptor[] customContributors); diff --git a/src/Castle.Windsor/MicroKernel/IKernel.cs b/src/Castle.Windsor/MicroKernel/IKernel.cs index 0bccaa6091..d11fb6d5d8 100644 --- a/src/Castle.Windsor/MicroKernel/IKernel.cs +++ b/src/Castle.Windsor/MicroKernel/IKernel.cs @@ -198,7 +198,7 @@ IKernel AddFacility(Action onCreate) /// Registers the components with the . The instances of are produced by fluent registration API. /// Most common entry points are method to register a single type or (recommended in most cases) /// . - /// Let the Intellisense drive you through the fluent API past those entry points. For details see the documentation at http://j.mp/WindsorApi + /// Let the Intellisense drive you through the fluent API past those entry points. /// /// /// diff --git a/src/Castle.Windsor/MicroKernel/IKernelInternal.cs b/src/Castle.Windsor/MicroKernel/IKernelInternal.cs index 3ca646b85d..64a99f9dea 100644 --- a/src/Castle.Windsor/MicroKernel/IKernelInternal.cs +++ b/src/Castle.Windsor/MicroKernel/IKernelInternal.cs @@ -45,13 +45,13 @@ public interface IKernelInternal : IKernel ILifestyleManager CreateLifestyleManager(ComponentModel model, IComponentActivator activator); - IHandler LoadHandlerByName(string key, Type service, IDictionary arguments); + IHandler LoadHandlerByName(string key, Type service, Arguments arguments); - IHandler LoadHandlerByType(string key, Type service, IDictionary arguments); + IHandler LoadHandlerByType(string key, Type service, Arguments arguments); IDisposable OptimizeDependencyResolution(); - object Resolve(Type service, IDictionary arguments, IReleasePolicy policy, bool ignoreParentContext = false); + object Resolve(Type service, Arguments arguments, IReleasePolicy policy, bool ignoreParentContext = false); /// /// Returns a component instance by the key @@ -61,9 +61,9 @@ public interface IKernelInternal : IKernel /// /// /// - object Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy); + object Resolve(string key, Type service, Arguments arguments, IReleasePolicy policy); - Array ResolveAll(Type service, IDictionary arguments, IReleasePolicy policy); + Array ResolveAll(Type service, Arguments arguments, IReleasePolicy policy); IHandler CreateHandler(ComponentModel model); diff --git a/src/Castle.Windsor/MicroKernel/IKernel_Resolve.cs b/src/Castle.Windsor/MicroKernel/IKernel_Resolve.cs index 149a3d5c8c..d5553a65ed 100644 --- a/src/Castle.Windsor/MicroKernel/IKernel_Resolve.cs +++ b/src/Castle.Windsor/MicroKernel/IKernel_Resolve.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel { using System; - using System.Collections; public partial interface IKernel : IKernelEvents, IDisposable { @@ -31,16 +30,7 @@ public partial interface IKernel : IKernelEvents, IDisposable /// /// /// - object Resolve(Type service, IDictionary arguments); - - /// - /// Returns the component instance by the service type - /// using dynamic arguments - /// - /// Service to resolve - /// Arguments to resolve the services - /// - object Resolve(Type service, object argumentsAsAnonymousType); + object Resolve(Type service, Arguments arguments); /// /// Returns a component instance by the key @@ -56,15 +46,7 @@ public partial interface IKernel : IKernelEvents, IDisposable /// /// /// - T Resolve(IDictionary arguments); - - /// - /// Returns the component instance by the service type - /// using dynamic arguments - /// - /// Arguments to resolve the services - /// - T Resolve(object argumentsAsAnonymousType); + T Resolve(Arguments arguments); /// /// Returns the component instance by the component key @@ -87,7 +69,7 @@ public partial interface IKernel : IKernelEvents, IDisposable /// Component's key /// /// The Component instance - T Resolve(String key, IDictionary arguments); + T Resolve(string key, Arguments arguments); /// /// Returns a component instance by the key @@ -96,7 +78,7 @@ public partial interface IKernel : IKernelEvents, IDisposable /// /// /// - object Resolve(String key, Type service, IDictionary arguments); + object Resolve(string key, Type service, Arguments arguments); /// /// Returns all the valid component instances by @@ -111,15 +93,7 @@ public partial interface IKernel : IKernelEvents, IDisposable /// /// The service type /// Arguments to resolve the services - Array ResolveAll(Type service, IDictionary arguments); - - /// - /// Returns all the valid component instances by - /// the service type - /// - /// The service type - /// Arguments to resolve the services - Array ResolveAll(Type service, object argumentsAsAnonymousType); + Array ResolveAll(Type service, Arguments arguments); /// /// Returns component instances that implement TService @@ -133,13 +107,6 @@ public partial interface IKernel : IKernelEvents, IDisposable /// /// /// - TService[] ResolveAll(IDictionary arguments); - - /// - /// Returns component instances that implement TService - /// - /// - /// - TService[] ResolveAll(object argumentsAsAnonymousType); + TService[] ResolveAll(Arguments arguments); } } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Internal/LazyEx.cs b/src/Castle.Windsor/MicroKernel/Internal/LazyEx.cs index 20e9d2fa1f..6144b6f852 100644 --- a/src/Castle.Windsor/MicroKernel/Internal/LazyEx.cs +++ b/src/Castle.Windsor/MicroKernel/Internal/LazyEx.cs @@ -22,7 +22,7 @@ public class LazyEx : Lazy, IDisposable { private readonly IKernel kernel; - public LazyEx(IKernel kernel, IDictionary arguments) + public LazyEx(IKernel kernel, Arguments arguments) : base(() => kernel.Resolve(arguments)) { this.kernel = kernel; @@ -34,7 +34,7 @@ public LazyEx(IKernel kernel, string overrideComponentName) this.kernel = kernel; } - public LazyEx(IKernel kernel, string overrideComponentName, IDictionary arguments) + public LazyEx(IKernel kernel, string overrideComponentName, Arguments arguments) : base(() => kernel.Resolve(overrideComponentName, arguments)) { this.kernel = kernel; diff --git a/src/Castle.Windsor/MicroKernel/Lifestyle/SingletonLifestyleManager.cs b/src/Castle.Windsor/MicroKernel/Lifestyle/SingletonLifestyleManager.cs index 5c47e696cf..5367ddee22 100644 --- a/src/Castle.Windsor/MicroKernel/Lifestyle/SingletonLifestyleManager.cs +++ b/src/Castle.Windsor/MicroKernel/Lifestyle/SingletonLifestyleManager.cs @@ -17,6 +17,7 @@ namespace Castle.MicroKernel.Lifestyle using System; using Castle.Core.Internal; + using Castle.MicroKernel.ComponentActivator; using Castle.MicroKernel.Context; /// @@ -69,7 +70,7 @@ public override object Resolve(CreationContext context, IReleasePolicy releasePo public object GetContextInstance(CreationContext context) { - return context.GetContextualProperty(ComponentActivator); + return context.GetContextualProperty(DefaultComponentActivator.InstanceStash); } } } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/ModelBuilder/DefaultComponentModelBuilder.cs b/src/Castle.Windsor/MicroKernel/ModelBuilder/DefaultComponentModelBuilder.cs index b78c132878..ab160376e3 100644 --- a/src/Castle.Windsor/MicroKernel/ModelBuilder/DefaultComponentModelBuilder.cs +++ b/src/Castle.Windsor/MicroKernel/ModelBuilder/DefaultComponentModelBuilder.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel.ModelBuilder { using System; - using System.Collections; using System.Collections.Generic; using Castle.Core; @@ -68,12 +67,7 @@ public void AddContributor(IContributeComponentModelConstruction contributor) /// Constructs a new ComponentModel by invoking /// the registered contributors. /// - /// - /// - /// - /// - /// - public ComponentModel BuildModel(ComponentName name, Type[] services, Type classType, IDictionary extendedProperties) + public ComponentModel BuildModel(ComponentName name, Type[] services, Type classType, Arguments extendedProperties) { var model = new ComponentModel(name, services, classType, extendedProperties); contributors.ForEach(c => c.ProcessModel(kernel, model)); diff --git a/src/Castle.Windsor/MicroKernel/ModelBuilder/Descriptors/CustomDependencyDescriptor.cs b/src/Castle.Windsor/MicroKernel/ModelBuilder/Descriptors/CustomDependencyDescriptor.cs index 0af38f5750..15728db608 100644 --- a/src/Castle.Windsor/MicroKernel/ModelBuilder/Descriptors/CustomDependencyDescriptor.cs +++ b/src/Castle.Windsor/MicroKernel/ModelBuilder/Descriptors/CustomDependencyDescriptor.cs @@ -14,26 +14,23 @@ namespace Castle.MicroKernel.ModelBuilder.Descriptors { - using System; - using System.Collections; - using Castle.Core; using Castle.Core.Internal; using Castle.MicroKernel.Registration; public class CustomDependencyDescriptor : IComponentModelDescriptor { - private readonly IDictionary dictionary; + private readonly Arguments arguments; private readonly Property[] properties; - public CustomDependencyDescriptor(params Property[] properties) + public CustomDependencyDescriptor(Arguments arguments) { - this.properties = properties; + this.arguments = arguments; } - public CustomDependencyDescriptor(IDictionary dictionary) + public CustomDependencyDescriptor(params Property[] properties) { - this.dictionary = dictionary; + this.properties = properties; } public void BuildComponentModel(IKernel kernel, ComponentModel model) @@ -42,9 +39,9 @@ public void BuildComponentModel(IKernel kernel, ComponentModel model) public void ConfigureComponentModel(IKernel kernel, ComponentModel model) { - if (dictionary != null) + if (arguments != null) { - foreach (DictionaryEntry property in dictionary) + foreach (var property in arguments) { model.CustomDependencies[property.Key] = property.Value; } diff --git a/src/Castle.Windsor/MicroKernel/Registration/ComponentDependencyRegistrationExtensions.cs b/src/Castle.Windsor/MicroKernel/Registration/ComponentDependencyRegistrationExtensions.cs deleted file mode 100644 index 56d3159f3a..0000000000 --- a/src/Castle.Windsor/MicroKernel/Registration/ComponentDependencyRegistrationExtensions.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2004-2011 Castle Project - http://www.castleproject.org/ -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace Castle.MicroKernel.Registration -{ - using System; - using System.Collections; - using System.ComponentModel; - - using Castle.Core; - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class ComponentDependencyRegistrationExtensions - { - /// - /// Inserts a new named argument with given key. If an argument for this name already exists, it will be overwritten. - /// - public static IDictionary Insert(this IDictionary arguments, string key, object value) - { - arguments[key] = value; - return arguments; - } - - /// - /// Inserts a new typed argument with given type. If an argument for this type already exists, it will be overwritten. - /// - public static IDictionary Insert(this IDictionary arguments, Type dependencyType, object value) - { - arguments[dependencyType] = value; - return arguments; - } - - /// - /// Inserts a set of typed arguments. Property names of the anonymous type will be used as key. - /// - public static IDictionary InsertAnonymous(this IDictionary arguments, object namedArgumentsAsAnonymousType) - { - foreach (DictionaryEntry item in new ReflectionBasedDictionaryAdapter(namedArgumentsAsAnonymousType)) - { - arguments[item.Key] = item.Value; - } - - return arguments; - } - - /// - /// Inserts a new typed argument with given type. If an argument for this type already exists, it will be overwritten. - /// - public static IDictionary InsertTyped(this IDictionary arguments, TDependencyType value) - { - arguments[typeof(TDependencyType)] = value; - return arguments; - } - - /// - /// Inserts a set of typed arguments. Actual type of the arguments will be used as key. - /// - public static IDictionary InsertTypedCollection(this IDictionary arguments, object[] typedArgumentsArray) - { - foreach (var item in typedArgumentsArray) - { - arguments[item.GetType()] = item; - } - - return arguments; - } - } -} \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Registration/ComponentRegistration.cs b/src/Castle.Windsor/MicroKernel/Registration/ComponentRegistration.cs index 86749535da..b8541c6c55 100644 --- a/src/Castle.Windsor/MicroKernel/Registration/ComponentRegistration.cs +++ b/src/Castle.Windsor/MicroKernel/Registration/ComponentRegistration.cs @@ -272,24 +272,31 @@ public ComponentRegistration DependsOn(params Dependency[] dependencie /// /// Uses a dictionary of key/value pairs, to specify custom dependencies. - /// /// - /// The dependencies. - /// - public ComponentRegistration DependsOn(IDictionary dependencies) + public ComponentRegistration DependsOn(Arguments dependencies) { return AddDescriptor(new CustomDependencyDescriptor(dependencies)); } + /// + /// Uses a dictionary of key/value pairs, to specify custom dependencies. + /// + public ComponentRegistration DependsOn(IDictionary dependencies) + { + var arguments = new Arguments(); + foreach (DictionaryEntry item in dependencies) + { + arguments.Add(item.Key, item.Value); + } + return DependsOn(arguments); + } + /// /// Uses an (anonymous) object as a dictionary, to specify custom dependencies. - /// /// - /// The dependencies. - /// public ComponentRegistration DependsOn(object dependenciesAsAnonymousType) { - return AddDescriptor(new CustomDependencyDescriptor(new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType))); + return DependsOn(new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType)); } /// @@ -333,7 +340,7 @@ public ComponentRegistration DependsOn(DynamicParametersWithContextRes } /// - /// Allows custom dependencies to by defined dyncamically. + /// Allows custom dependencies to by defined dynamically. /// /// The delegate used for providing dynamic parameters. /// diff --git a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersDelegate.cs b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersDelegate.cs index 39a8b125bb..44d97780a9 100644 --- a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersDelegate.cs +++ b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersDelegate.cs @@ -14,7 +14,5 @@ namespace Castle.MicroKernel.Registration { - using System.Collections; - - public delegate void DynamicParametersDelegate(IKernel kernel, IDictionary parameters); + public delegate void DynamicParametersDelegate(IKernel kernel, Arguments arguments); } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersResolveDelegate.cs b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersResolveDelegate.cs index b8034ec0d0..72afeb0329 100644 --- a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersResolveDelegate.cs +++ b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersResolveDelegate.cs @@ -14,9 +14,7 @@ namespace Castle.MicroKernel.Registration { - using System.Collections; - using Castle.MicroKernel.Handlers; - public delegate ComponentReleasingDelegate DynamicParametersResolveDelegate(IKernel kernel, IDictionary parameters); + public delegate ComponentReleasingDelegate DynamicParametersResolveDelegate(IKernel kernel, Arguments arguments); } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersWithContextResolveDelegate.cs b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersWithContextResolveDelegate.cs index fa6d9087d6..5c9d84ee30 100644 --- a/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersWithContextResolveDelegate.cs +++ b/src/Castle.Windsor/MicroKernel/Registration/DynamicParametersWithContextResolveDelegate.cs @@ -14,11 +14,9 @@ namespace Castle.MicroKernel.Registration { - using System.Collections; - using Castle.MicroKernel.Context; using Castle.MicroKernel.Handlers; public delegate ComponentReleasingDelegate DynamicParametersWithContextResolveDelegate( - IKernel kernel, CreationContext creationContext, IDictionary parameters); + IKernel kernel, CreationContext creationContext, Arguments arguments); } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Resolvers/ILazyComponentLoader.cs b/src/Castle.Windsor/MicroKernel/Resolvers/ILazyComponentLoader.cs index e7b06a952b..bb48f2e840 100644 --- a/src/Castle.Windsor/MicroKernel/Resolvers/ILazyComponentLoader.cs +++ b/src/Castle.Windsor/MicroKernel/Resolvers/ILazyComponentLoader.cs @@ -43,6 +43,6 @@ public interface ILazyComponentLoader /// to register component for requested key/service combination (when one of the elements is null, it should be ignored as well). /// When implementer does not want to register the requested component it must return null. /// - IRegistration Load(string name, Type service, IDictionary arguments); + IRegistration Load(string name, Type service, Arguments arguments); } } \ No newline at end of file diff --git a/src/Castle.Windsor/MicroKernel/Resolvers/LazyOfTComponentLoader.cs b/src/Castle.Windsor/MicroKernel/Resolvers/LazyOfTComponentLoader.cs index edbcad3926..de0b708419 100644 --- a/src/Castle.Windsor/MicroKernel/Resolvers/LazyOfTComponentLoader.cs +++ b/src/Castle.Windsor/MicroKernel/Resolvers/LazyOfTComponentLoader.cs @@ -15,7 +15,6 @@ namespace Castle.MicroKernel.Resolvers { using System; - using System.Collections; using System.Reflection; using Castle.Core; @@ -28,7 +27,7 @@ namespace Castle.MicroKernel.Resolvers [Singleton] public class LazyOfTComponentLoader : ILazyComponentLoader { - public IRegistration Load(string name, Type service, IDictionary arguments) + public IRegistration Load(string name, Type service, Arguments arguments) { if (service == null) { diff --git a/src/Castle.Windsor/Windsor/Diagnostics/IUsingContainerAsServiceLocatorDiagnostic.cs b/src/Castle.Windsor/Windsor/Diagnostics/IUsingContainerAsServiceLocatorDiagnostic.cs index 94b129dace..a458894aa7 100644 --- a/src/Castle.Windsor/Windsor/Diagnostics/IUsingContainerAsServiceLocatorDiagnostic.cs +++ b/src/Castle.Windsor/Windsor/Diagnostics/IUsingContainerAsServiceLocatorDiagnostic.cs @@ -18,7 +18,7 @@ namespace Castle.Windsor.Diagnostics /// /// Detects components that are not extending Windsor's infrastructure yet depend on the container which usually means they use the container as service locator - /// which is a bad practice and should be avoided. Consult the documentation for more details: http://j.mp/WindsorSL + /// which is a bad practice and should be avoided. /// public interface IUsingContainerAsServiceLocatorDiagnostic : IDiagnostic { diff --git a/src/Castle.Windsor/Windsor/Extensions/WindsorContainerExtensions.cs b/src/Castle.Windsor/Windsor/Extensions/WindsorContainerExtensions.cs new file mode 100644 index 0000000000..38e597aeb5 --- /dev/null +++ b/src/Castle.Windsor/Windsor/Extensions/WindsorContainerExtensions.cs @@ -0,0 +1,72 @@ +// Copyright 2004-2018 Castle Project - http://www.castleproject.org/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Castle.Windsor +{ + using System; + using System.Collections.Generic; + + using Castle.MicroKernel; + + public static class WindsorContainerExtensions + { + /// + /// Returns a component instance by the service. + /// + public static object Resolve(this IWindsorContainer container, Type service, IEnumerable> arguments) + { + return container.Kernel.Resolve(service, new Arguments().AddNamed(arguments)); + } + + /// + /// Returns a component instance by the key. + /// + public static object Resolve(this IWindsorContainer container, string key, Type service, IEnumerable> arguments) + { + return container.Kernel.Resolve(key, service, new Arguments().AddNamed(arguments)); + } + + /// + /// Returns a component instance by the service. + /// + public static T Resolve(this IWindsorContainer container, IEnumerable> arguments) + { + return (T)container.Kernel.Resolve(typeof(T), new Arguments().AddNamed(arguments)); + } + + /// + /// Returns a component instance by the key. + /// + public static T Resolve(this IWindsorContainer container, string key, IEnumerable> arguments) + { + return container.Kernel.Resolve(key, new Arguments().AddNamed(arguments)); + } + + /// + /// Resolve all valid components that match this type by passing dependencies as arguments. + /// + public static Array ResolveAll(this IWindsorContainer container, Type service, IEnumerable> arguments) + { + return container.Kernel.ResolveAll(service, new Arguments().AddNamed(arguments)); + } + + /// + /// Resolve all valid components that match this type. + /// + public static T[] ResolveAll(this IWindsorContainer container, IEnumerable> arguments) + { + return (T[])container.ResolveAll(typeof(T), new Arguments().AddNamed(arguments)); + } + } +} \ No newline at end of file diff --git a/src/Castle.Windsor/Windsor/IWindsorContainer.cs b/src/Castle.Windsor/Windsor/IWindsorContainer.cs index 46a2412a9b..a44bffc617 100644 --- a/src/Castle.Windsor/Windsor/IWindsorContainer.cs +++ b/src/Castle.Windsor/Windsor/IWindsorContainer.cs @@ -15,7 +15,6 @@ namespace Castle.Windsor { using System; - using System.Collections; using System.Reflection; using Castle.MicroKernel; @@ -23,10 +22,9 @@ namespace Castle.Windsor using Castle.Windsor.Installer; /// - /// The IWindsorContainer interface exposes all the - /// functionality the Windsor implements. + /// The IWindsorContainer interface exposes all the functionality that Windsor implements. /// - public partial interface IWindsorContainer : IDisposable + public interface IWindsorContainer : IDisposable { /// /// Returns the inner instance of the MicroKernel @@ -85,7 +83,7 @@ IWindsorContainer AddFacility(Action onCreate) IWindsorContainer GetChildContainer(string name); /// - /// Runs the so that they can register components in the container. For details see the documentation at http://j.mp/WindsorInstall + /// Runs the so that they can register components in the container. /// /// /// In addition to instantiating and passing every installer inline you can use helper methods on (Action onCreate) /// Registers the components with the . The instances of are produced by fluent registration API. /// Most common entry points are method to register a single type or (recommended in most cases) /// . - /// Let the Intellisense drive you through the fluent API past those entry points. For details see the documentation at http://j.mp/WindsorApi + /// Let the Intellisense drive you through the fluent API past those entry points. /// /// /// @@ -144,7 +142,7 @@ IWindsorContainer AddFacility(Action onCreate) /// /// /// - object Resolve(String key, Type service); + object Resolve(string key, Type service); /// /// Returns a component instance by the service @@ -157,17 +155,9 @@ IWindsorContainer AddFacility(Action onCreate) /// Returns a component instance by the service /// /// - /// + /// Arguments to resolve the service. /// - object Resolve(Type service, IDictionary arguments); - - /// - /// Returns a component instance by the service - /// - /// - /// - /// - object Resolve(Type service, object argumentsAsAnonymousType); + object Resolve(Type service, Arguments arguments); /// /// Returns a component instance by the service @@ -180,17 +170,9 @@ IWindsorContainer AddFacility(Action onCreate) /// Returns a component instance by the service /// /// Service type - /// - /// The component instance - T Resolve(IDictionary arguments); - - /// - /// Returns a component instance by the service - /// - /// Service type - /// + /// Arguments to resolve the service. /// The component instance - T Resolve(object argumentsAsAnonymousType); + T Resolve(Arguments arguments); /// /// Returns a component instance by the key @@ -198,43 +180,25 @@ IWindsorContainer AddFacility(Action onCreate) /// Component's key /// Service type /// The Component instance - T Resolve(String key); - - /// - /// Returns a component instance by the key - /// - /// Service type - /// Component's key - /// - /// The Component instance - T Resolve(String key, IDictionary arguments); + T Resolve(string key); /// /// Returns a component instance by the key /// /// Service type /// Component's key - /// + /// Arguments to resolve the service. /// The Component instance - T Resolve(String key, object argumentsAsAnonymousType); + T Resolve(string key, Arguments arguments); /// /// Returns a component instance by the key /// /// /// - /// + /// Arguments to resolve the service. /// - object Resolve(String key, Type service, IDictionary arguments); - - /// - /// Returns a component instance by the key - /// - /// - /// - /// - /// - object Resolve(String key, Type service, object argumentsAsAnonymousType); + object Resolve(string key, Type service, Arguments arguments); /// /// Resolve all valid components that match this type. @@ -251,29 +215,15 @@ IWindsorContainer AddFacility(Action onCreate) /// /// Resolve all valid components that match this service /// the service to match - /// Arguments to resolve the service - /// - Array ResolveAll(Type service, IDictionary arguments); - - /// - /// Resolve all valid components that match this service - /// the service to match - /// Arguments to resolve the service - /// - Array ResolveAll(Type service, object argumentsAsAnonymousType); - - /// - /// Resolve all valid components that match this type. - /// The service type - /// Arguments to resolve the service + /// Arguments to resolve the service. /// - T[] ResolveAll(IDictionary arguments); + Array ResolveAll(Type service, Arguments arguments); /// /// Resolve all valid components that match this type. /// The service type - /// Arguments to resolve the service + /// Arguments to resolve the service. /// - T[] ResolveAll(object argumentsAsAnonymousType); + T[] ResolveAll(Arguments arguments); } } \ No newline at end of file diff --git a/src/Castle.Windsor/Windsor/WindsorContainer.cs b/src/Castle.Windsor/Windsor/WindsorContainer.cs index 495458b2db..6c0fa8f675 100644 --- a/src/Castle.Windsor/Windsor/WindsorContainer.cs +++ b/src/Castle.Windsor/Windsor/WindsorContainer.cs @@ -15,14 +15,12 @@ namespace Castle.Windsor { using System; - using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Text; using System.Threading; - using Castle.Core; using Castle.MicroKernel; using Castle.MicroKernel.Registration; using Castle.MicroKernel.SubSystems.Configuration; @@ -40,7 +38,7 @@ namespace Castle.Windsor [Serializable] [DebuggerDisplay("{name,nq}")] [DebuggerTypeProxy(typeof(KernelDebuggerProxy))] - public partial class WindsorContainer : + public class WindsorContainer : #if FEATURE_REMOTING MarshalByRefObject, #endif @@ -412,7 +410,7 @@ public IWindsorContainer GetChildContainer(string name) } /// - /// Runs the so that they can register components in the container. For details see the documentation at http://j.mp/WindsorInstall + /// Runs the so that they can register components in the container. /// /// /// In addition to instantiating and passing every installer inline you can use helper methods on . The instances of are produced by fluent registration API. /// Most common entry points are method to register a single type or (recommended in most cases) /// . - /// Let the Intellisense drive you through the fluent API past those entry points. For details see the documentation at http://j.mp/WindsorApi + /// Let the Intellisense drive you through the fluent API past those entry points. /// /// /// @@ -528,22 +526,11 @@ public virtual void RemoveChildContainer(IWindsorContainer childContainer) /// /// /// - public virtual object Resolve(Type service, IDictionary arguments) + public virtual object Resolve(Type service, Arguments arguments) { return kernel.Resolve(service, arguments); } - /// - /// Returns a component instance by the service - /// - /// - /// - /// - public virtual object Resolve(Type service, object argumentsAsAnonymousType) - { - return Resolve(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns a component instance by the service /// @@ -572,67 +559,33 @@ public virtual object Resolve(String key, Type service) /// /// /// - public virtual object Resolve(String key, Type service, IDictionary arguments) + public virtual object Resolve(string key, Type service, Arguments arguments) { return kernel.Resolve(key, service, arguments); } - /// - /// Returns a component instance by the key - /// - /// - /// - /// - /// - public virtual object Resolve(String key, Type service, object argumentsAsAnonymousType) - { - return kernel.Resolve(key, service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns a component instance by the service /// /// /// /// - public T Resolve(IDictionary arguments) + public T Resolve(Arguments arguments) { return (T)kernel.Resolve(typeof(T), arguments); } - /// - /// Returns a component instance by the service - /// - /// - /// - /// - public T Resolve(object argumentsAsAnonymousType) - { - return (T)kernel.Resolve(typeof(T), new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns a component instance by the key /// /// /// /// - public virtual T Resolve(String key, IDictionary arguments) + public virtual T Resolve(string key, Arguments arguments) { return (T)kernel.Resolve(key, typeof(T), arguments); } - /// - /// Returns a component instance by the key - /// - /// - /// - /// - public virtual T Resolve(String key, object argumentsAsAnonymousType) - { - return (T)kernel.Resolve(key, typeof(T), new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Returns a component instance by the service /// @@ -662,41 +615,37 @@ public T[] ResolveAll() return (T[])ResolveAll(typeof(T)); } + /// + /// Resolve all valid components that match this type. + /// + /// + /// public Array ResolveAll(Type service) { return kernel.ResolveAll(service); } - public Array ResolveAll(Type service, IDictionary arguments) + /// + /// Resolve all valid components that match this type by passing dependencies as arguments. + /// + /// + /// + /// + public Array ResolveAll(Type service, Arguments arguments) { return kernel.ResolveAll(service, arguments); } - public Array ResolveAll(Type service, object argumentsAsAnonymousType) - { - return ResolveAll(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - /// /// Resolve all valid components that match this type. /// The service type /// Arguments to resolve the service /// - public T[] ResolveAll(IDictionary arguments) + public T[] ResolveAll(Arguments arguments) { return (T[])ResolveAll(typeof(T), arguments); } - /// - /// Resolve all valid components that match this type. - /// The service type - /// Arguments to resolve the service - /// - public T[] ResolveAll(object argumentsAsAnonymousType) - { - return ResolveAll(new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType)); - } - private XmlInterpreter GetInterpreter(string configurationUri) { try