/src/packages/SimpleInjector.Extensions.1.5.0.12238/lib/net35/SimpleInjector.Extensions.xml
XML | 1776 lines | 1660 code | 116 blank | 0 comment | 0 complexity | fd91840dfcf29e54dc64196e1ec4eda1 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?xml version="1.0"?>
- <doc>
- <assembly>
- <name>SimpleInjector.Extensions</name>
- </assembly>
- <members>
- <member name="T:SimpleInjector.Extensions.DecoratorExtensions">
- <summary>
- Extension methods for applying decorators.
- </summary>
- </member>
- <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type)">
- <summary>
- Ensures that the supplied <paramref name="decoratorType"/> decorator is returned, wrapping the
- original registered <paramref name="serviceType"/>, by injecting that service type into the
- constructor of the supplied <paramref name="decoratorType"/>. Multiple decorators may be applied
- to the same <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and
- non-generic service types.
- </summary>
- <remarks>
- <para>
- The <b>RegisterDecorator</b> method works by hooking onto the container's
- <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
- <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
- decoration of types that are resolved using unregistered type resolution. The
- <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
- extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
- use <b>RegisterDecorator</b> on the same generic service type as <b>RegisterOpenGeneric</b>.
- </para>
- <para>
- Multiple decorators can be applied to the same service type. The order in which they are registered
- is the order they get applied in. This means that the decorator that gets registered first, gets
- applied first, which means that the next registered decorator, will wrap the first decorator, which
- wraps the original service type.
- </para>
- <para>
- The registered <paramref name="decoratorType"/> must have a single public constructor. Constructor
- injection will be used on that type, and although it may have many constructor arguments, it must
- have exactly one argument of the type of <paramref name="serviceType"/>, or an argument of type
- <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. An exception will be
- thrown when this is not the case.
- </para>
- <para>
- The registered <paramref name="decoratorType"/> may have a constructor with an argument of type
- <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. In this case, the
- will not inject the decorated <paramref name="serviceType"/> itself into the
- <paramref name="decoratorType"/> instance, but it will inject a <see cref="T:System.Func`1"/> that allows
- creating instances of the decorated type, according to the lifestyle of that type. This enables
- more advanced scenarios, such as executing the decorated types on a different thread, or executing
- decorated instance within a certain scope (such as a lifetime scope).
- </para>
- </remarks>
- <example>
- The following example shows the definition of a generic <b>ICommandHandler<T></b> interface,
- a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
- <b>ValidatorCommandHandlerDecorator<T></b> that acts as a decorator for that interface.
- <code lang="cs"><![CDATA[
- using System.ComponentModel.DataAnnotations;
- using System.Diagnostics;
- using System.Linq;
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- using SimpleInjector;
- using SimpleInjector.Extensions;
-
- public interface ICommandHandler<TCommand>
- {
- void Handle(TCommand command);
- }
-
- public class CustomerMovedCommand
- {
- [Required]
- public int CustomerId { get; set; }
-
- [Required]
- public Address Address { get; set; }
- }
-
- public class CustomerMovedCommandHandler
- : ICommandHandler<CustomerMovedCommand>
- {
- public void Handle(CustomerMovedCommand command)
- {
- // some logic
- }
- }
-
- // Decorator that validates commands before they get executed.
- public class ValidatorCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly Container container;
-
- public ValidatorCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- Container container)
- {
- this.decoratedHandler = decoratedHandler;
- this.container = container;
- }
-
- public void Handle(TCommand command)
- {
- this.Validate(command);
-
- this.decoratedHandler.Handle(command);
- }
-
- private void Validate(TCommand command)
- {
- var validationContext =
- new ValidationContext(command, this.container, null);
-
- Validator.ValidateObject(command, validationContext);
- }
- }
-
- // Decorator that measures the time it takes to execute a command.
- public class MonitoringCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly ILogger logger;
-
- public MonitoringCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- ILogger logger)
- {
- this.decoratedHandler = decoratedHandler;
- this.logger = logger;
- }
-
- public void Handle(TCommand command)
- {
- var watch = Stopwatch.StartNew();
-
- this.decoratedHandler.Handle(command);
-
- this.logger.Log(string.Format("{0} executed in {1} ms.",
- command.GetType().Name, watch.ElapsedMilliseconds));
- }
- }
-
- [TestMethod]
- public static void TestRegisterOpenGenericDecorator()
- {
- // Arrange
- var container = new Container();
-
- container.RegisterSingle<ILogger, DebugLogger>();
-
- // Search the given assembly and register all concrete types that
- // implement ICommandHandler<TCommand>.
- container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
- typeof(ICommandHandler<>).Assembly);
-
- // Wrap all ICommandHandler<TCommand> service types with a decorator
- // that measures and logs the duration of that handler.
- container.RegisterDecorator(typeof(ICommandHandler<>),
- typeof(MonitoringCommandHandlerDecorator<>));
-
- // Wrap all ICommandHandler<TCommand> types (in this case it will
- // wrap the monitoring decorator), but only if the TCommand contains
- // any properties.
- container.RegisterDecorator(typeof(ICommandHandler<>),
- typeof(ValidatorCommandHandlerDecorator<>), context =>
- {
- var commandType = context.ServiceType.GetGenericArguments()[0];
- bool mustDecorate = commandType.GetProperties().Any();
- return mustDecorate;
- });
-
- // Act
- var handler =
- container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
-
- // Assert
- Assert.IsInstanceOfType(handler,
- typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
- }
- ]]></code>
- </example>
- <param name="container">The container to make the registrations in.</param>
- <param name="serviceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="decoratorType"/>.</param>
- <param name="decoratorType">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="serviceType"/>, or <paramref name="decoratorType"/> are null
- references.</exception>
- <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
- an open generic type, when <paramref name="decoratorType"/> does not inherit from or implement
- <paramref name="serviceType"/>, when <paramref name="decoratorType"/> does not
- have a single public constructor, or when <paramref name="decoratorType"/> does not
- contain a constructor that has exactly one argument of type
- <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
- <paramref name="serviceType"/>.</exception>
- </member>
- <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">
- <summary>
- Ensures that the supplied <paramref name="decoratorType"/> decorator is returned when the supplied
- <paramref name="predicate"/> returns <b>true</b>, wrapping the original registered
- <paramref name="serviceType"/>, by injecting that service type into the constructor of the
- supplied <paramref name="decoratorType"/>. Multiple decorators may be applied to the same
- <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and non-generic
- service types.
- </summary>
- <remarks>
- <para>
- The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
- <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
- <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
- decoration of types that are resolved using unregistered type resolution. The
- <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
- extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
- use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
- </para>
- <para>
- Multiple decorators can be applied to the same service type. The order in which they are registered
- is the order they get applied in. This means that the decorator that gets registered first, gets
- applied first, which means that the next registered decorator, will wrap the first decorator, which
- wraps the original service type.
- </para>
- <para>
- The registered <paramref name="decoratorType"/> must have a single public constructor. Constructor
- injection will be used on that type, and although it may have many constructor arguments, it must
- have exactly one argument of the type of <paramref name="serviceType"/>, or an argument of type
- <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. An exception will be
- thrown when this is not the case.
- </para>
- <para>
- The registered <paramref name="decoratorType"/> may have a constructor with an argument of type
- <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. In this case, the
- will not inject the decorated <paramref name="serviceType"/> itself into the
- <paramref name="decoratorType"/> instance, but it will inject a <see cref="T:System.Func`1"/> that allows
- creating instances of the decorated type, according to the lifestyle of that type. This enables
- more advanced scenarios, such as executing the decorated types on a different thread, or executing
- decorated instance within a certain scope (such as a lifetime scope).
- </para>
- </remarks>
- <example>
- The following example shows the definition of a generic <b>ICommandHandler<T></b> interface,
- a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
- <b>ValidatorCommandHandlerDecorator<T></b> that acts as a decorator for that interface.
- <code lang="cs"><![CDATA[
- using System.ComponentModel.DataAnnotations;
- using System.Diagnostics;
- using System.Linq;
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- using SimpleInjector;
- using SimpleInjector.Extensions;
-
- public interface ICommandHandler<TCommand>
- {
- void Handle(TCommand command);
- }
-
- public class CustomerMovedCommand
- {
- [Required]
- public int CustomerId { get; set; }
-
- [Required]
- public Address Address { get; set; }
- }
-
- public class CustomerMovedCommandHandler
- : ICommandHandler<CustomerMovedCommand>
- {
- public void Handle(CustomerMovedCommand command)
- {
- // some logic
- }
- }
-
- // Decorator that validates commands before they get executed.
- public class ValidatorCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly Container container;
-
- public ValidatorCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- Container container)
- {
- this.decoratedHandler = decoratedHandler;
- this.container = container;
- }
-
- public void Handle(TCommand command)
- {
- this.Validate(command);
-
- this.decoratedHandler.Handle(command);
- }
-
- private void Validate(TCommand command)
- {
- var validationContext =
- new ValidationContext(command, this.container, null);
-
- Validator.ValidateObject(command, validationContext);
- }
- }
-
- // Decorator that measures the time it takes to execute a command.
- public class MonitoringCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly ILogger logger;
-
- public MonitoringCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- ILogger logger)
- {
- this.decoratedHandler = decoratedHandler;
- this.logger = logger;
- }
-
- public void Handle(TCommand command)
- {
- var watch = Stopwatch.StartNew();
-
- this.decoratedHandler.Handle(command);
-
- this.logger.Log(string.Format("{0} executed in {1} ms.",
- command.GetType().Name, watch.ElapsedMilliseconds));
- }
- }
-
- [TestMethod]
- public static void TestRegisterOpenGenericDecorator()
- {
- // Arrange
- var container = new Container();
-
- container.RegisterSingle<ILogger, DebugLogger>();
-
- // Search the given assembly and register all concrete types that
- // implement ICommandHandler<TCommand>.
- container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
- typeof(ICommandHandler<>).Assembly);
-
- // Wrap all ICommandHandler<TCommand> service types with a decorator
- // that measures and logs the duration of that handler.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(MonitoringCommandHandlerDecorator<>));
-
- // Wrap all ICommandHandler<TCommand> types (in this case it will
- // wrap the monitoring decorator), but only if the TCommand contains
- // any properties.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(ValidatorCommandHandlerDecorator<>), context =>
- {
- var commandType = context.ServiceType.GetGenericArguments()[0];
- bool mustDecorate = commandType.GetProperties().Any();
- return mustDecorate;
- });
-
- // Act
- var handler =
- container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
-
- // Assert
- Assert.IsInstanceOfType(handler,
- typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
- }
- ]]></code>
- </example>
- <param name="container">The container to make the registrations in.</param>
- <param name="serviceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="decoratorType"/>.</param>
- <param name="decoratorType">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <param name="predicate">The predicate that determines whether the
- <paramref name="decoratorType"/> must be applied to a service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="serviceType"/>, <paramref name="decoratorType"/>, or
- <paramref name="predicate"/> are null references.</exception>
- <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
- an open generic type, when <paramref name="decoratorType"/> does not inherit from or
- implement <paramref name="serviceType"/>, when <paramref name="decoratorType"/>
- does not have a single public constructor, or when <paramref name="decoratorType"/> does
- not contain a constructor that has exactly one argument of type
- <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
- <paramref name="serviceType"/>.</exception>
- </member>
- <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterSingleDecorator(SimpleInjector.Container,System.Type,System.Type)">
- <summary>
- Ensures that a single instance of the supplied <paramref name="decoratorType"/> decorator is
- returned, wrapping the original registered <paramref name="serviceType"/>, by injecting that
- service type into the constructor of the supplied <paramref name="decoratorType"/>. Multiple
- decorators may be applied to the same <paramref name="serviceType"/>. Decorators can be applied
- to both open, closed, and non-generic service types.
- </summary>
- <remarks>
- <para>
- This method ensures that a single instance of the supplied <paramref name="decoratorType"/> is
- returned, no matter what the lifestyle of the wrapped service type is. Use with care, because the
- wrapped service type will also become a singleton. This method is especially useful when use for
- injecting <see cref="T:System.Func`1"/> factory methods, which will allow the wrapped service type to get
- it's own lifestyle back.
- </para>
- <para>
- Please see the <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type)">RegisterDecorator</see> method
- for more information.
- </para>
- </remarks>
- <param name="container">The container to make the registrations in.</param>
- <param name="serviceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="decoratorType"/>.</param>
- <param name="decoratorType">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="serviceType"/>, or <paramref name="decoratorType"/> are null
- references.</exception>
- <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
- an open generic type, when <paramref name="decoratorType"/> does not inherit from or implement
- <paramref name="serviceType"/>, when <paramref name="decoratorType"/> does not
- have a single public constructor, or when <paramref name="decoratorType"/> does not
- contain a constructor that has exactly one argument of type
- <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
- <paramref name="serviceType"/>.</exception>
- </member>
- <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterSingleDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">
- <summary>
- Ensures that the supplied <paramref name="decoratorType"/> decorator is returned when the supplied
- <paramref name="predicate"/> returns <b>true</b>, wrapping the original registered
- <paramref name="serviceType"/>, by injecting that service type into the constructor of the
- supplied <paramref name="decoratorType"/>. Multiple decorators may be applied to the same
- <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and non-generic
- service types.
- </summary>
- <remarks>
- <para>
- This method ensures that a single instance of the supplied <paramref name="decoratorType"/> is
- returned, no matter what the lifestyle of the wrapped service type is. Use with care, because the
- wrapped service type will also become a singleton. This method is especially useful when use for
- injecting <see cref="T:System.Func`1"/> factory methods, which will allow the wrapped service type to get
- it's own lifestyle back.
- </para>
- <para>
- Please see the
- <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">RegisterDecorator</see>
- method for more information.
- </para>
- </remarks>
- <param name="container">The container to make the registrations in.</param>
- <param name="serviceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="decoratorType"/>.</param>
- <param name="decoratorType">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <param name="predicate">The predicate that determines whether the
- <paramref name="decoratorType"/> must be applied to a service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="serviceType"/>, <paramref name="decoratorType"/>, or
- <paramref name="predicate"/> are null references.</exception>
- <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
- an open generic type, when <paramref name="decoratorType"/> does not inherit from or
- implement <paramref name="serviceType"/>, when <paramref name="decoratorType"/>
- does not have a single public constructor, or when <paramref name="decoratorType"/> does
- not contain a constructor that has exactly one argument of type
- <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
- <paramref name="serviceType"/>.</exception>
- </member>
- <member name="T:SimpleInjector.Extensions.DecoratorPredicateContext">
- <summary>
- An instance of this type will be supplied to the <see cref="T:System.Predicate`1"/>
- delegate that is that is supplied to the
- <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">RegisterDecorator</see>
- overload that takes this delegate. This type contains information about the decoration that is about
- to be applied and it allows users to examine the given instance to see whether the decorator should
- be applied or not.
- </summary>
- </member>
- <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.ServiceType">
- <summary>
- Gets the closed generic service type for which the decorator is about to be applied. The original
- service type will be returned, even if other decorators have already been applied to this type.
- </summary>
- <value>The closed generic service type.</value>
- </member>
- <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.ImplementationType">
- <summary>
- Gets the type of the implementation that is created by the container and for which the decorator
- is about to be applied. The original implementation type will be returned, even if other decorators
- have already been applied to this type. Please not that the implementation type can not always be
- determined. In that case the closed generic service type will be returned.
- </summary>
- <value>The implementation type.</value>
- </member>
- <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.AppliedDecorators">
- <summary>
- Gets the list of the types of decorators that have already been applied to this instance.
- </summary>
- <value>The applied decorators.</value>
- </member>
- <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.Expression">
- <summary>
- Gets the current <see cref="P:SimpleInjector.Extensions.DecoratorPredicateContext.Expression"/> object that describes the intention to create a new
- instance with its currently applied decorators.
- </summary>
- <value>The current expression that is about to be decorated.</value>
- </member>
- <member name="T:SimpleInjector.Extensions.Decorators.IDecoratableEnumerable">
- <summary>
- An IDecoratableEnumerable is a special enumerable that can be used more efficiently by the container
- to apply decorators to, with the biggest noticable difference that the registered predicate, will be
- checked for each service in the collection.
- </summary>
- </member>
- <member name="T:SimpleInjector.Extensions.Decorators.DecoratorExpressionInterceptor">
- <summary>
- Hooks into the building process and adds a decorator if needed.
- </summary>
- </member>
- <member name="T:SimpleInjector.Extensions.GenericArgumentFinder">
- <summary>
- Allows retrieving the concrete types of the generic type arguments of that must be used to create a
- closed generic implementation of a given open generic implementation, based on on the concrete
- arguments of the given closed base type.
- </summary>
- </member>
- <member name="T:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping">
- <summary>
- A map containing a generic argument (such as T) and the concrete type (such as Int32) that it
- represents.
- </summary>
- </member>
- <member name="M:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping.System#IEquatable{SimpleInjector#Extensions#GenericArgumentFinder#ArgumentMapping}#Equals(SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping)">
- <summary>Implements equality. Needed for doing LINQ distinct operations.</summary>
- <param name="other">The other to compare to.</param>
- <returns>True or false.</returns>
- </member>
- <member name="M:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping.GetHashCode">
- <summary>Overrides the default hash code. Needed for doing LINQ distinct operations.</summary>
- <returns>An 32 bit integer.</returns>
- </member>
- <member name="T:SimpleInjector.Extensions.GenericArgumentFinder.TypeConstraintValidator">
- <summary>
- Allows validating an ArgumentMapping.
- </summary>
- </member>
- <member name="T:SimpleInjector.Extensions.GenericDecoratorExtensions">
- <summary>
- Extension methods for applying generic decorators.
- </summary>
- </member>
- <member name="M:SimpleInjector.Extensions.GenericDecoratorExtensions.RegisterOpenGenericDecorator(SimpleInjector.Container,System.Type,System.Type)">
- <summary>
- Ensures that a closed generic version of the supplied <paramref name="openGenericDecorator"/>
- decorator is returned, wrapping the original closed generic version of the registered
- <paramref name="openGenericServiceType"/>, by injecting that service type into the constructor
- of the supplied <paramref name="openGenericDecorator"/>. Multiple decorators may be applied to the
- same <paramref name="openGenericServiceType"/>.
- </summary>
- <remarks>
- <para>
- The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
- <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
- <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
- decoration of types that are resolved using unregistered type resolution. The
- <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
- extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
- use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
- </para>
- <para>
- Multiple decorators can be applied to the same service type. The order in which they are registered
- is the order they get applied in. This means that the decorator that gets registered first, gets
- applied first, which means that the next registered decorator, will wrap the first decorator, which
- wraps the original service type.
- </para>
- </remarks>
- <example>
- The following example shows the definition of a generic <b>ICommandHandler<T></b> interface,
- a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
- <b>ValidatorCommandHandlerDecorator<T></b> that acts as a decorator for that interface.
- <code lang="cs"><![CDATA[
- using System.ComponentModel.DataAnnotations;
- using System.Diagnostics;
- using System.Linq;
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- using SimpleInjector;
- using SimpleInjector.Extensions;
-
- public interface ICommandHandler<TCommand>
- {
- void Handle(TCommand command);
- }
-
- public class CustomerMovedCommand
- {
- [Required]
- public int CustomerId { get; set; }
-
- [Required]
- public Address Address { get; set; }
- }
-
- public class CustomerMovedCommandHandler
- : ICommandHandler<CustomerMovedCommand>
- {
- public void Handle(CustomerMovedCommand command)
- {
- // some logic
- }
- }
-
- // Decorator that validates commands before they get executed.
- public class ValidatorCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly Container container;
-
- public ValidatorCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- Container container)
- {
- this.decoratedHandler = decoratedHandler;
- this.container = container;
- }
-
- public void Handle(TCommand command)
- {
- this.Validate(command);
-
- this.decoratedHandler.Handle(command);
- }
-
- private void Validate(TCommand command)
- {
- var validationContext =
- new ValidationContext(command, this.container, null);
-
- Validator.ValidateObject(command, validationContext);
- }
- }
-
- // Decorator that measures the time it takes to execute a command.
- public class MonitoringCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly ILogger logger;
-
- public MonitoringCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- ILogger logger)
- {
- this.decoratedHandler = decoratedHandler;
- this.logger = logger;
- }
-
- public void Handle(TCommand command)
- {
- var watch = Stopwatch.StartNew();
-
- this.decoratedHandler.Handle(command);
-
- this.logger.Log(string.Format("{0} executed in {1} ms.",
- command.GetType().Name, watch.ElapsedMilliseconds));
- }
- }
-
- [TestMethod]
- public static void TestRegisterOpenGenericDecorator()
- {
- // Arrange
- var container = new Container();
-
- container.RegisterSingle<ILogger, DebugLogger>();
-
- // Search the given assembly and register all concrete types that
- // implement ICommandHandler<TCommand>.
- container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
- typeof(ICommandHandler<>).Assembly);
-
- // Wrap all ICommandHandler<TCommand> service types with a decorator
- // that measures and logs the duration of that handler.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(MonitoringCommandHandlerDecorator<>));
-
- // Wrap all ICommandHandler<TCommand> types (in this case it will
- // wrap the monitoring decorator), but only if the TCommand contains
- // any properties.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(ValidatorCommandHandlerDecorator<>), c =>
- {
- var commandType = c.ServiceType.GetGenericArguments()[0];
- bool mustDecorate = commandType.GetProperties().Any();
- return mustDecorate;
- });
-
- // Act
- var handler =
- container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
-
- // Assert
- Assert.IsInstanceOfType(handler,
- typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
- }
- ]]></code>
- </example>
- <param name="container">The container to make the registrations in.</param>
- <param name="openGenericServiceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="openGenericDecorator"/>.</param>
- <param name="openGenericDecorator">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="openGenericServiceType"/>, or <paramref name="openGenericDecorator"/> are null
- references.</exception>
- <exception cref="T:System.ArgumentException">Thrown when <paramref name="openGenericServiceType"/> is not
- an open generic type, when <paramref name="openGenericDecorator"/> does not inherit from or implement
- <paramref name="openGenericServiceType"/>, when <paramref name="openGenericDecorator"/> does not
- have a single public constructor, or when <paramref name="openGenericDecorator"/> does not
- contain a constructor that has exactly one argument of type
- <paramref name="openGenericServiceType"/>.</exception>
- </member>
- <member name="M:SimpleInjector.Extensions.GenericDecoratorExtensions.RegisterOpenGenericDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.GenericDecoratorExtensions.PredicateContext})">
- <summary>
- Ensures that a closed generic version of the supplied <paramref name="openGenericDecorator"/>
- decorator is returned, wrapping the original closed generic version of the registered
- <paramref name="openGenericServiceType"/>, by injecting that service type into the constructor
- of the supplied <paramref name="openGenericDecorator"/>. Multiple decorators may be applied to the
- same <paramref name="openGenericServiceType"/>.
- </summary>
- <remarks>
- <para>
- The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
- <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
- <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
- decoration of types that are resolved using unregistered type resolution. The
- <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
- extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
- use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
- </para>
- <para>
- Multiple decorators can be applied to the same service type. The order in which they are registered
- is the order they get applied in. This means that the decorator that gets registered first, gets
- applied first, which means that the next registered decorator, will wrap the first decorator, which
- wraps the original service type.
- </para>
- </remarks>
- <example>
- The following example shows the definition of a generic <b>ICommandHandler<T></b> interface,
- a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
- <b>ValidatorCommandHandlerDecorator<T></b> that acts as a decorator for that interface.
- <code lang="cs"><![CDATA[
- using System.ComponentModel.DataAnnotations;
- using System.Diagnostics;
- using System.Linq;
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- using SimpleInjector;
- using SimpleInjector.Extensions;
-
- public interface ICommandHandler<TCommand>
- {
- void Handle(TCommand command);
- }
-
- public class CustomerMovedCommand
- {
- [Required]
- public int CustomerId { get; set; }
-
- [Required]
- public Address Address { get; set; }
- }
-
- public class CustomerMovedCommandHandler
- : ICommandHandler<CustomerMovedCommand>
- {
- public void Handle(CustomerMovedCommand command)
- {
- // some logic
- }
- }
-
- // Decorator that validates commands before they get executed.
- public class ValidatorCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly Container container;
-
- public ValidatorCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- Container container)
- {
- this.decoratedHandler = decoratedHandler;
- this.container = container;
- }
-
- public void Handle(TCommand command)
- {
- this.Validate(command);
-
- this.decoratedHandler.Handle(command);
- }
-
- private void Validate(TCommand command)
- {
- var validationContext =
- new ValidationContext(command, this.container, null);
-
- Validator.ValidateObject(command, validationContext);
- }
- }
-
- // Decorator that measures the time it takes to execute a command.
- public class MonitoringCommandHandlerDecorator<TCommand>
- : ICommandHandler<TCommand>
- {
- private readonly ICommandHandler<TCommand> decoratedHandler;
- private readonly ILogger logger;
-
- public MonitoringCommandHandlerDecorator(
- ICommandHandler<TCommand> decoratedHandler,
- ILogger logger)
- {
- this.decoratedHandler = decoratedHandler;
- this.logger = logger;
- }
-
- public void Handle(TCommand command)
- {
- var watch = Stopwatch.StartNew();
-
- this.decoratedHandler.Handle(command);
-
- this.logger.Log(string.Format("{0} executed in {1} ms.",
- command.GetType().Name, watch.ElapsedMilliseconds));
- }
- }
-
- [TestMethod]
- public static void TestRegisterOpenGenericDecorator()
- {
- // Arrange
- var container = new Container();
-
- container.RegisterSingle<ILogger, DebugLogger>();
-
- // Search the given assembly and register all concrete types that
- // implement ICommandHandler<TCommand>.
- container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
- typeof(ICommandHandler<>).Assembly);
-
- // Wrap all ICommandHandler<TCommand> service types with a decorator
- // that measures and logs the duration of that handler.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(MonitoringCommandHandlerDecorator<>));
-
- // Wrap all ICommandHandler<TCommand> types (in this case it will
- // wrap the monitoring decorator), but only if the TCommand contains
- // any properties.
- container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
- typeof(ValidatorCommandHandlerDecorator<>), c =>
- {
- var commandType = c.ServiceType.GetGenericArguments()[0];
- bool mustDecorate = commandType.GetProperties().Any();
- return mustDecorate;
- });
-
- // Act
- var handler =
- container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
-
- // Assert
- Assert.IsInstanceOfType(handler,
- typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
- }
- ]]></code>
- </example>
- <param name="container">The container to make the registrations in.</param>
- <param name="openGenericServiceType">The definition of the open generic service type that will
- be wrapped by the given <paramref name="openGenericDecorator"/>.</param>
- <param name="openGenericDecorator">The definition of the open generic decorator type that will
- be used to wrap the original service type.</param>
- <param name="predicate">The predicate that determines whether the
- <paramref name="openGenericDecorator"/> must be applied to a service type.</param>
- <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
- <paramref name="openGenericServiceType"/>, <paramref name="openGenericDecorator"/>, or
- <paramref name="predicate"/> are null references.</exception>
- <except…
Large files files are truncated, but you can click here to view the full file