PageRenderTime 70ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/packages/SimpleInjector.Extensions.1.5.0.12238/lib/net35/SimpleInjector.Extensions.xml

http://fluentjqgrid.codeplex.com
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

  1. <?xml version="1.0"?>
  2. <doc>
  3. <assembly>
  4. <name>SimpleInjector.Extensions</name>
  5. </assembly>
  6. <members>
  7. <member name="T:SimpleInjector.Extensions.DecoratorExtensions">
  8. <summary>
  9. Extension methods for applying decorators.
  10. </summary>
  11. </member>
  12. <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type)">
  13. <summary>
  14. Ensures that the supplied <paramref name="decoratorType"/> decorator is returned, wrapping the
  15. original registered <paramref name="serviceType"/>, by injecting that service type into the
  16. constructor of the supplied <paramref name="decoratorType"/>. Multiple decorators may be applied
  17. to the same <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and
  18. non-generic service types.
  19. </summary>
  20. <remarks>
  21. <para>
  22. The <b>RegisterDecorator</b> method works by hooking onto the container's
  23. <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
  24. <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
  25. decoration of types that are resolved using unregistered type resolution. The
  26. <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
  27. extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
  28. use <b>RegisterDecorator</b> on the same generic service type as <b>RegisterOpenGeneric</b>.
  29. </para>
  30. <para>
  31. Multiple decorators can be applied to the same service type. The order in which they are registered
  32. is the order they get applied in. This means that the decorator that gets registered first, gets
  33. applied first, which means that the next registered decorator, will wrap the first decorator, which
  34. wraps the original service type.
  35. </para>
  36. <para>
  37. The registered <paramref name="decoratorType"/> must have a single public constructor. Constructor
  38. injection will be used on that type, and although it may have many constructor arguments, it must
  39. have exactly one argument of the type of <paramref name="serviceType"/>, or an argument of type
  40. <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. An exception will be
  41. thrown when this is not the case.
  42. </para>
  43. <para>
  44. The registered <paramref name="decoratorType"/> may have a constructor with an argument of type
  45. <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. In this case, the
  46. will not inject the decorated <paramref name="serviceType"/> itself into the
  47. <paramref name="decoratorType"/> instance, but it will inject a <see cref="T:System.Func`1"/> that allows
  48. creating instances of the decorated type, according to the lifestyle of that type. This enables
  49. more advanced scenarios, such as executing the decorated types on a different thread, or executing
  50. decorated instance within a certain scope (such as a lifetime scope).
  51. </para>
  52. </remarks>
  53. <example>
  54. The following example shows the definition of a generic <b>ICommandHandler&lt;T&gt;</b> interface,
  55. a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
  56. <b>ValidatorCommandHandlerDecorator&lt;T&gt;</b> that acts as a decorator for that interface.
  57. <code lang="cs"><![CDATA[
  58. using System.ComponentModel.DataAnnotations;
  59. using System.Diagnostics;
  60. using System.Linq;
  61. using Microsoft.VisualStudio.TestTools.UnitTesting;
  62. using SimpleInjector;
  63. using SimpleInjector.Extensions;
  64. public interface ICommandHandler<TCommand>
  65. {
  66. void Handle(TCommand command);
  67. }
  68. public class CustomerMovedCommand
  69. {
  70. [Required]
  71. public int CustomerId { get; set; }
  72. [Required]
  73. public Address Address { get; set; }
  74. }
  75. public class CustomerMovedCommandHandler
  76. : ICommandHandler<CustomerMovedCommand>
  77. {
  78. public void Handle(CustomerMovedCommand command)
  79. {
  80. // some logic
  81. }
  82. }
  83. // Decorator that validates commands before they get executed.
  84. public class ValidatorCommandHandlerDecorator<TCommand>
  85. : ICommandHandler<TCommand>
  86. {
  87. private readonly ICommandHandler<TCommand> decoratedHandler;
  88. private readonly Container container;
  89. public ValidatorCommandHandlerDecorator(
  90. ICommandHandler<TCommand> decoratedHandler,
  91. Container container)
  92. {
  93. this.decoratedHandler = decoratedHandler;
  94. this.container = container;
  95. }
  96. public void Handle(TCommand command)
  97. {
  98. this.Validate(command);
  99. this.decoratedHandler.Handle(command);
  100. }
  101. private void Validate(TCommand command)
  102. {
  103. var validationContext =
  104. new ValidationContext(command, this.container, null);
  105. Validator.ValidateObject(command, validationContext);
  106. }
  107. }
  108. // Decorator that measures the time it takes to execute a command.
  109. public class MonitoringCommandHandlerDecorator<TCommand>
  110. : ICommandHandler<TCommand>
  111. {
  112. private readonly ICommandHandler<TCommand> decoratedHandler;
  113. private readonly ILogger logger;
  114. public MonitoringCommandHandlerDecorator(
  115. ICommandHandler<TCommand> decoratedHandler,
  116. ILogger logger)
  117. {
  118. this.decoratedHandler = decoratedHandler;
  119. this.logger = logger;
  120. }
  121. public void Handle(TCommand command)
  122. {
  123. var watch = Stopwatch.StartNew();
  124. this.decoratedHandler.Handle(command);
  125. this.logger.Log(string.Format("{0} executed in {1} ms.",
  126. command.GetType().Name, watch.ElapsedMilliseconds));
  127. }
  128. }
  129. [TestMethod]
  130. public static void TestRegisterOpenGenericDecorator()
  131. {
  132. // Arrange
  133. var container = new Container();
  134. container.RegisterSingle<ILogger, DebugLogger>();
  135. // Search the given assembly and register all concrete types that
  136. // implement ICommandHandler<TCommand>.
  137. container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
  138. typeof(ICommandHandler<>).Assembly);
  139. // Wrap all ICommandHandler<TCommand> service types with a decorator
  140. // that measures and logs the duration of that handler.
  141. container.RegisterDecorator(typeof(ICommandHandler<>),
  142. typeof(MonitoringCommandHandlerDecorator<>));
  143. // Wrap all ICommandHandler<TCommand> types (in this case it will
  144. // wrap the monitoring decorator), but only if the TCommand contains
  145. // any properties.
  146. container.RegisterDecorator(typeof(ICommandHandler<>),
  147. typeof(ValidatorCommandHandlerDecorator<>), context =>
  148. {
  149. var commandType = context.ServiceType.GetGenericArguments()[0];
  150. bool mustDecorate = commandType.GetProperties().Any();
  151. return mustDecorate;
  152. });
  153. // Act
  154. var handler =
  155. container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
  156. // Assert
  157. Assert.IsInstanceOfType(handler,
  158. typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
  159. }
  160. ]]></code>
  161. </example>
  162. <param name="container">The container to make the registrations in.</param>
  163. <param name="serviceType">The definition of the open generic service type that will
  164. be wrapped by the given <paramref name="decoratorType"/>.</param>
  165. <param name="decoratorType">The definition of the open generic decorator type that will
  166. be used to wrap the original service type.</param>
  167. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  168. <paramref name="serviceType"/>, or <paramref name="decoratorType"/> are null
  169. references.</exception>
  170. <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
  171. an open generic type, when <paramref name="decoratorType"/> does not inherit from or implement
  172. <paramref name="serviceType"/>, when <paramref name="decoratorType"/> does not
  173. have a single public constructor, or when <paramref name="decoratorType"/> does not
  174. contain a constructor that has exactly one argument of type
  175. <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
  176. <paramref name="serviceType"/>.</exception>
  177. </member>
  178. <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">
  179. <summary>
  180. Ensures that the supplied <paramref name="decoratorType"/> decorator is returned when the supplied
  181. <paramref name="predicate"/> returns <b>true</b>, wrapping the original registered
  182. <paramref name="serviceType"/>, by injecting that service type into the constructor of the
  183. supplied <paramref name="decoratorType"/>. Multiple decorators may be applied to the same
  184. <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and non-generic
  185. service types.
  186. </summary>
  187. <remarks>
  188. <para>
  189. The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
  190. <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
  191. <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
  192. decoration of types that are resolved using unregistered type resolution. The
  193. <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
  194. extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
  195. use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
  196. </para>
  197. <para>
  198. Multiple decorators can be applied to the same service type. The order in which they are registered
  199. is the order they get applied in. This means that the decorator that gets registered first, gets
  200. applied first, which means that the next registered decorator, will wrap the first decorator, which
  201. wraps the original service type.
  202. </para>
  203. <para>
  204. The registered <paramref name="decoratorType"/> must have a single public constructor. Constructor
  205. injection will be used on that type, and although it may have many constructor arguments, it must
  206. have exactly one argument of the type of <paramref name="serviceType"/>, or an argument of type
  207. <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. An exception will be
  208. thrown when this is not the case.
  209. </para>
  210. <para>
  211. The registered <paramref name="decoratorType"/> may have a constructor with an argument of type
  212. <see cref="T:System.Func`1"/> where <b>T</b> is <paramref name="serviceType"/>. In this case, the
  213. will not inject the decorated <paramref name="serviceType"/> itself into the
  214. <paramref name="decoratorType"/> instance, but it will inject a <see cref="T:System.Func`1"/> that allows
  215. creating instances of the decorated type, according to the lifestyle of that type. This enables
  216. more advanced scenarios, such as executing the decorated types on a different thread, or executing
  217. decorated instance within a certain scope (such as a lifetime scope).
  218. </para>
  219. </remarks>
  220. <example>
  221. The following example shows the definition of a generic <b>ICommandHandler&lt;T&gt;</b> interface,
  222. a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
  223. <b>ValidatorCommandHandlerDecorator&lt;T&gt;</b> that acts as a decorator for that interface.
  224. <code lang="cs"><![CDATA[
  225. using System.ComponentModel.DataAnnotations;
  226. using System.Diagnostics;
  227. using System.Linq;
  228. using Microsoft.VisualStudio.TestTools.UnitTesting;
  229. using SimpleInjector;
  230. using SimpleInjector.Extensions;
  231. public interface ICommandHandler<TCommand>
  232. {
  233. void Handle(TCommand command);
  234. }
  235. public class CustomerMovedCommand
  236. {
  237. [Required]
  238. public int CustomerId { get; set; }
  239. [Required]
  240. public Address Address { get; set; }
  241. }
  242. public class CustomerMovedCommandHandler
  243. : ICommandHandler<CustomerMovedCommand>
  244. {
  245. public void Handle(CustomerMovedCommand command)
  246. {
  247. // some logic
  248. }
  249. }
  250. // Decorator that validates commands before they get executed.
  251. public class ValidatorCommandHandlerDecorator<TCommand>
  252. : ICommandHandler<TCommand>
  253. {
  254. private readonly ICommandHandler<TCommand> decoratedHandler;
  255. private readonly Container container;
  256. public ValidatorCommandHandlerDecorator(
  257. ICommandHandler<TCommand> decoratedHandler,
  258. Container container)
  259. {
  260. this.decoratedHandler = decoratedHandler;
  261. this.container = container;
  262. }
  263. public void Handle(TCommand command)
  264. {
  265. this.Validate(command);
  266. this.decoratedHandler.Handle(command);
  267. }
  268. private void Validate(TCommand command)
  269. {
  270. var validationContext =
  271. new ValidationContext(command, this.container, null);
  272. Validator.ValidateObject(command, validationContext);
  273. }
  274. }
  275. // Decorator that measures the time it takes to execute a command.
  276. public class MonitoringCommandHandlerDecorator<TCommand>
  277. : ICommandHandler<TCommand>
  278. {
  279. private readonly ICommandHandler<TCommand> decoratedHandler;
  280. private readonly ILogger logger;
  281. public MonitoringCommandHandlerDecorator(
  282. ICommandHandler<TCommand> decoratedHandler,
  283. ILogger logger)
  284. {
  285. this.decoratedHandler = decoratedHandler;
  286. this.logger = logger;
  287. }
  288. public void Handle(TCommand command)
  289. {
  290. var watch = Stopwatch.StartNew();
  291. this.decoratedHandler.Handle(command);
  292. this.logger.Log(string.Format("{0} executed in {1} ms.",
  293. command.GetType().Name, watch.ElapsedMilliseconds));
  294. }
  295. }
  296. [TestMethod]
  297. public static void TestRegisterOpenGenericDecorator()
  298. {
  299. // Arrange
  300. var container = new Container();
  301. container.RegisterSingle<ILogger, DebugLogger>();
  302. // Search the given assembly and register all concrete types that
  303. // implement ICommandHandler<TCommand>.
  304. container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
  305. typeof(ICommandHandler<>).Assembly);
  306. // Wrap all ICommandHandler<TCommand> service types with a decorator
  307. // that measures and logs the duration of that handler.
  308. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  309. typeof(MonitoringCommandHandlerDecorator<>));
  310. // Wrap all ICommandHandler<TCommand> types (in this case it will
  311. // wrap the monitoring decorator), but only if the TCommand contains
  312. // any properties.
  313. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  314. typeof(ValidatorCommandHandlerDecorator<>), context =>
  315. {
  316. var commandType = context.ServiceType.GetGenericArguments()[0];
  317. bool mustDecorate = commandType.GetProperties().Any();
  318. return mustDecorate;
  319. });
  320. // Act
  321. var handler =
  322. container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
  323. // Assert
  324. Assert.IsInstanceOfType(handler,
  325. typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
  326. }
  327. ]]></code>
  328. </example>
  329. <param name="container">The container to make the registrations in.</param>
  330. <param name="serviceType">The definition of the open generic service type that will
  331. be wrapped by the given <paramref name="decoratorType"/>.</param>
  332. <param name="decoratorType">The definition of the open generic decorator type that will
  333. be used to wrap the original service type.</param>
  334. <param name="predicate">The predicate that determines whether the
  335. <paramref name="decoratorType"/> must be applied to a service type.</param>
  336. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  337. <paramref name="serviceType"/>, <paramref name="decoratorType"/>, or
  338. <paramref name="predicate"/> are null references.</exception>
  339. <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
  340. an open generic type, when <paramref name="decoratorType"/> does not inherit from or
  341. implement <paramref name="serviceType"/>, when <paramref name="decoratorType"/>
  342. does not have a single public constructor, or when <paramref name="decoratorType"/> does
  343. not contain a constructor that has exactly one argument of type
  344. <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
  345. <paramref name="serviceType"/>.</exception>
  346. </member>
  347. <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterSingleDecorator(SimpleInjector.Container,System.Type,System.Type)">
  348. <summary>
  349. Ensures that a single instance of the supplied <paramref name="decoratorType"/> decorator is
  350. returned, wrapping the original registered <paramref name="serviceType"/>, by injecting that
  351. service type into the constructor of the supplied <paramref name="decoratorType"/>. Multiple
  352. decorators may be applied to the same <paramref name="serviceType"/>. Decorators can be applied
  353. to both open, closed, and non-generic service types.
  354. </summary>
  355. <remarks>
  356. <para>
  357. This method ensures that a single instance of the supplied <paramref name="decoratorType"/> is
  358. returned, no matter what the lifestyle of the wrapped service type is. Use with care, because the
  359. wrapped service type will also become a singleton. This method is especially useful when use for
  360. injecting <see cref="T:System.Func`1"/> factory methods, which will allow the wrapped service type to get
  361. it's own lifestyle back.
  362. </para>
  363. <para>
  364. Please see the <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type)">RegisterDecorator</see> method
  365. for more information.
  366. </para>
  367. </remarks>
  368. <param name="container">The container to make the registrations in.</param>
  369. <param name="serviceType">The definition of the open generic service type that will
  370. be wrapped by the given <paramref name="decoratorType"/>.</param>
  371. <param name="decoratorType">The definition of the open generic decorator type that will
  372. be used to wrap the original service type.</param>
  373. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  374. <paramref name="serviceType"/>, or <paramref name="decoratorType"/> are null
  375. references.</exception>
  376. <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
  377. an open generic type, when <paramref name="decoratorType"/> does not inherit from or implement
  378. <paramref name="serviceType"/>, when <paramref name="decoratorType"/> does not
  379. have a single public constructor, or when <paramref name="decoratorType"/> does not
  380. contain a constructor that has exactly one argument of type
  381. <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
  382. <paramref name="serviceType"/>.</exception>
  383. </member>
  384. <member name="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterSingleDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">
  385. <summary>
  386. Ensures that the supplied <paramref name="decoratorType"/> decorator is returned when the supplied
  387. <paramref name="predicate"/> returns <b>true</b>, wrapping the original registered
  388. <paramref name="serviceType"/>, by injecting that service type into the constructor of the
  389. supplied <paramref name="decoratorType"/>. Multiple decorators may be applied to the same
  390. <paramref name="serviceType"/>. Decorators can be applied to both open, closed, and non-generic
  391. service types.
  392. </summary>
  393. <remarks>
  394. <para>
  395. This method ensures that a single instance of the supplied <paramref name="decoratorType"/> is
  396. returned, no matter what the lifestyle of the wrapped service type is. Use with care, because the
  397. wrapped service type will also become a singleton. This method is especially useful when use for
  398. injecting <see cref="T:System.Func`1"/> factory methods, which will allow the wrapped service type to get
  399. it's own lifestyle back.
  400. </para>
  401. <para>
  402. Please see the
  403. <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">RegisterDecorator</see>
  404. method for more information.
  405. </para>
  406. </remarks>
  407. <param name="container">The container to make the registrations in.</param>
  408. <param name="serviceType">The definition of the open generic service type that will
  409. be wrapped by the given <paramref name="decoratorType"/>.</param>
  410. <param name="decoratorType">The definition of the open generic decorator type that will
  411. be used to wrap the original service type.</param>
  412. <param name="predicate">The predicate that determines whether the
  413. <paramref name="decoratorType"/> must be applied to a service type.</param>
  414. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  415. <paramref name="serviceType"/>, <paramref name="decoratorType"/>, or
  416. <paramref name="predicate"/> are null references.</exception>
  417. <exception cref="T:System.ArgumentException">Thrown when <paramref name="serviceType"/> is not
  418. an open generic type, when <paramref name="decoratorType"/> does not inherit from or
  419. implement <paramref name="serviceType"/>, when <paramref name="decoratorType"/>
  420. does not have a single public constructor, or when <paramref name="decoratorType"/> does
  421. not contain a constructor that has exactly one argument of type
  422. <paramref name="serviceType"/> or <see cref="T:System.Func`1"/> where <b>T</b> is
  423. <paramref name="serviceType"/>.</exception>
  424. </member>
  425. <member name="T:SimpleInjector.Extensions.DecoratorPredicateContext">
  426. <summary>
  427. An instance of this type will be supplied to the <see cref="T:System.Predicate`1"/>
  428. delegate that is that is supplied to the
  429. <see cref="M:SimpleInjector.Extensions.DecoratorExtensions.RegisterDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.DecoratorPredicateContext})">RegisterDecorator</see>
  430. overload that takes this delegate. This type contains information about the decoration that is about
  431. to be applied and it allows users to examine the given instance to see whether the decorator should
  432. be applied or not.
  433. </summary>
  434. </member>
  435. <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.ServiceType">
  436. <summary>
  437. Gets the closed generic service type for which the decorator is about to be applied. The original
  438. service type will be returned, even if other decorators have already been applied to this type.
  439. </summary>
  440. <value>The closed generic service type.</value>
  441. </member>
  442. <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.ImplementationType">
  443. <summary>
  444. Gets the type of the implementation that is created by the container and for which the decorator
  445. is about to be applied. The original implementation type will be returned, even if other decorators
  446. have already been applied to this type. Please not that the implementation type can not always be
  447. determined. In that case the closed generic service type will be returned.
  448. </summary>
  449. <value>The implementation type.</value>
  450. </member>
  451. <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.AppliedDecorators">
  452. <summary>
  453. Gets the list of the types of decorators that have already been applied to this instance.
  454. </summary>
  455. <value>The applied decorators.</value>
  456. </member>
  457. <member name="P:SimpleInjector.Extensions.DecoratorPredicateContext.Expression">
  458. <summary>
  459. Gets the current <see cref="P:SimpleInjector.Extensions.DecoratorPredicateContext.Expression"/> object that describes the intention to create a new
  460. instance with its currently applied decorators.
  461. </summary>
  462. <value>The current expression that is about to be decorated.</value>
  463. </member>
  464. <member name="T:SimpleInjector.Extensions.Decorators.IDecoratableEnumerable">
  465. <summary>
  466. An IDecoratableEnumerable is a special enumerable that can be used more efficiently by the container
  467. to apply decorators to, with the biggest noticable difference that the registered predicate, will be
  468. checked for each service in the collection.
  469. </summary>
  470. </member>
  471. <member name="T:SimpleInjector.Extensions.Decorators.DecoratorExpressionInterceptor">
  472. <summary>
  473. Hooks into the building process and adds a decorator if needed.
  474. </summary>
  475. </member>
  476. <member name="T:SimpleInjector.Extensions.GenericArgumentFinder">
  477. <summary>
  478. Allows retrieving the concrete types of the generic type arguments of that must be used to create a
  479. closed generic implementation of a given open generic implementation, based on on the concrete
  480. arguments of the given closed base type.
  481. </summary>
  482. </member>
  483. <member name="T:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping">
  484. <summary>
  485. A map containing a generic argument (such as T) and the concrete type (such as Int32) that it
  486. represents.
  487. </summary>
  488. </member>
  489. <member name="M:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping.System#IEquatable{SimpleInjector#Extensions#GenericArgumentFinder#ArgumentMapping}#Equals(SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping)">
  490. <summary>Implements equality. Needed for doing LINQ distinct operations.</summary>
  491. <param name="other">The other to compare to.</param>
  492. <returns>True or false.</returns>
  493. </member>
  494. <member name="M:SimpleInjector.Extensions.GenericArgumentFinder.ArgumentMapping.GetHashCode">
  495. <summary>Overrides the default hash code. Needed for doing LINQ distinct operations.</summary>
  496. <returns>An 32 bit integer.</returns>
  497. </member>
  498. <member name="T:SimpleInjector.Extensions.GenericArgumentFinder.TypeConstraintValidator">
  499. <summary>
  500. Allows validating an ArgumentMapping.
  501. </summary>
  502. </member>
  503. <member name="T:SimpleInjector.Extensions.GenericDecoratorExtensions">
  504. <summary>
  505. Extension methods for applying generic decorators.
  506. </summary>
  507. </member>
  508. <member name="M:SimpleInjector.Extensions.GenericDecoratorExtensions.RegisterOpenGenericDecorator(SimpleInjector.Container,System.Type,System.Type)">
  509. <summary>
  510. Ensures that a closed generic version of the supplied <paramref name="openGenericDecorator"/>
  511. decorator is returned, wrapping the original closed generic version of the registered
  512. <paramref name="openGenericServiceType"/>, by injecting that service type into the constructor
  513. of the supplied <paramref name="openGenericDecorator"/>. Multiple decorators may be applied to the
  514. same <paramref name="openGenericServiceType"/>.
  515. </summary>
  516. <remarks>
  517. <para>
  518. The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
  519. <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
  520. <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
  521. decoration of types that are resolved using unregistered type resolution. The
  522. <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
  523. extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
  524. use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
  525. </para>
  526. <para>
  527. Multiple decorators can be applied to the same service type. The order in which they are registered
  528. is the order they get applied in. This means that the decorator that gets registered first, gets
  529. applied first, which means that the next registered decorator, will wrap the first decorator, which
  530. wraps the original service type.
  531. </para>
  532. </remarks>
  533. <example>
  534. The following example shows the definition of a generic <b>ICommandHandler&lt;T&gt;</b> interface,
  535. a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
  536. <b>ValidatorCommandHandlerDecorator&lt;T&gt;</b> that acts as a decorator for that interface.
  537. <code lang="cs"><![CDATA[
  538. using System.ComponentModel.DataAnnotations;
  539. using System.Diagnostics;
  540. using System.Linq;
  541. using Microsoft.VisualStudio.TestTools.UnitTesting;
  542. using SimpleInjector;
  543. using SimpleInjector.Extensions;
  544. public interface ICommandHandler<TCommand>
  545. {
  546. void Handle(TCommand command);
  547. }
  548. public class CustomerMovedCommand
  549. {
  550. [Required]
  551. public int CustomerId { get; set; }
  552. [Required]
  553. public Address Address { get; set; }
  554. }
  555. public class CustomerMovedCommandHandler
  556. : ICommandHandler<CustomerMovedCommand>
  557. {
  558. public void Handle(CustomerMovedCommand command)
  559. {
  560. // some logic
  561. }
  562. }
  563. // Decorator that validates commands before they get executed.
  564. public class ValidatorCommandHandlerDecorator<TCommand>
  565. : ICommandHandler<TCommand>
  566. {
  567. private readonly ICommandHandler<TCommand> decoratedHandler;
  568. private readonly Container container;
  569. public ValidatorCommandHandlerDecorator(
  570. ICommandHandler<TCommand> decoratedHandler,
  571. Container container)
  572. {
  573. this.decoratedHandler = decoratedHandler;
  574. this.container = container;
  575. }
  576. public void Handle(TCommand command)
  577. {
  578. this.Validate(command);
  579. this.decoratedHandler.Handle(command);
  580. }
  581. private void Validate(TCommand command)
  582. {
  583. var validationContext =
  584. new ValidationContext(command, this.container, null);
  585. Validator.ValidateObject(command, validationContext);
  586. }
  587. }
  588. // Decorator that measures the time it takes to execute a command.
  589. public class MonitoringCommandHandlerDecorator<TCommand>
  590. : ICommandHandler<TCommand>
  591. {
  592. private readonly ICommandHandler<TCommand> decoratedHandler;
  593. private readonly ILogger logger;
  594. public MonitoringCommandHandlerDecorator(
  595. ICommandHandler<TCommand> decoratedHandler,
  596. ILogger logger)
  597. {
  598. this.decoratedHandler = decoratedHandler;
  599. this.logger = logger;
  600. }
  601. public void Handle(TCommand command)
  602. {
  603. var watch = Stopwatch.StartNew();
  604. this.decoratedHandler.Handle(command);
  605. this.logger.Log(string.Format("{0} executed in {1} ms.",
  606. command.GetType().Name, watch.ElapsedMilliseconds));
  607. }
  608. }
  609. [TestMethod]
  610. public static void TestRegisterOpenGenericDecorator()
  611. {
  612. // Arrange
  613. var container = new Container();
  614. container.RegisterSingle<ILogger, DebugLogger>();
  615. // Search the given assembly and register all concrete types that
  616. // implement ICommandHandler<TCommand>.
  617. container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
  618. typeof(ICommandHandler<>).Assembly);
  619. // Wrap all ICommandHandler<TCommand> service types with a decorator
  620. // that measures and logs the duration of that handler.
  621. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  622. typeof(MonitoringCommandHandlerDecorator<>));
  623. // Wrap all ICommandHandler<TCommand> types (in this case it will
  624. // wrap the monitoring decorator), but only if the TCommand contains
  625. // any properties.
  626. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  627. typeof(ValidatorCommandHandlerDecorator<>), c =>
  628. {
  629. var commandType = c.ServiceType.GetGenericArguments()[0];
  630. bool mustDecorate = commandType.GetProperties().Any();
  631. return mustDecorate;
  632. });
  633. // Act
  634. var handler =
  635. container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
  636. // Assert
  637. Assert.IsInstanceOfType(handler,
  638. typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
  639. }
  640. ]]></code>
  641. </example>
  642. <param name="container">The container to make the registrations in.</param>
  643. <param name="openGenericServiceType">The definition of the open generic service type that will
  644. be wrapped by the given <paramref name="openGenericDecorator"/>.</param>
  645. <param name="openGenericDecorator">The definition of the open generic decorator type that will
  646. be used to wrap the original service type.</param>
  647. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  648. <paramref name="openGenericServiceType"/>, or <paramref name="openGenericDecorator"/> are null
  649. references.</exception>
  650. <exception cref="T:System.ArgumentException">Thrown when <paramref name="openGenericServiceType"/> is not
  651. an open generic type, when <paramref name="openGenericDecorator"/> does not inherit from or implement
  652. <paramref name="openGenericServiceType"/>, when <paramref name="openGenericDecorator"/> does not
  653. have a single public constructor, or when <paramref name="openGenericDecorator"/> does not
  654. contain a constructor that has exactly one argument of type
  655. <paramref name="openGenericServiceType"/>.</exception>
  656. </member>
  657. <member name="M:SimpleInjector.Extensions.GenericDecoratorExtensions.RegisterOpenGenericDecorator(SimpleInjector.Container,System.Type,System.Type,System.Predicate{SimpleInjector.Extensions.GenericDecoratorExtensions.PredicateContext})">
  658. <summary>
  659. Ensures that a closed generic version of the supplied <paramref name="openGenericDecorator"/>
  660. decorator is returned, wrapping the original closed generic version of the registered
  661. <paramref name="openGenericServiceType"/>, by injecting that service type into the constructor
  662. of the supplied <paramref name="openGenericDecorator"/>. Multiple decorators may be applied to the
  663. same <paramref name="openGenericServiceType"/>.
  664. </summary>
  665. <remarks>
  666. <para>
  667. The <b>RegisterOpenGenericDecorator</b> method works by hooking onto the container's
  668. <see cref="E:SimpleInjector.Container.ExpressionBuilt">ExpressionBuilt</see> event. This event fires after the
  669. <see cref="E:SimpleInjector.Container.ResolveUnregisteredType">ResolveUnregisteredType</see> event, which allows
  670. decoration of types that are resolved using unregistered type resolution. The
  671. <see cref="M:SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric(SimpleInjector.Container,System.Type,System.Type)">RegisterOpenGeneric</see>
  672. extension method, for instance, hooks onto the <b>ResolveUnregisteredType</b>. This allows you to
  673. use <b>RegisterOpenGenericDecorator</b> on the same service type as <b>RegisterOpenGeneric</b>.
  674. </para>
  675. <para>
  676. Multiple decorators can be applied to the same service type. The order in which they are registered
  677. is the order they get applied in. This means that the decorator that gets registered first, gets
  678. applied first, which means that the next registered decorator, will wrap the first decorator, which
  679. wraps the original service type.
  680. </para>
  681. </remarks>
  682. <example>
  683. The following example shows the definition of a generic <b>ICommandHandler&lt;T&gt;</b> interface,
  684. a <b>CustomerMovedCommandHandler</b> implementing that interface, and a
  685. <b>ValidatorCommandHandlerDecorator&lt;T&gt;</b> that acts as a decorator for that interface.
  686. <code lang="cs"><![CDATA[
  687. using System.ComponentModel.DataAnnotations;
  688. using System.Diagnostics;
  689. using System.Linq;
  690. using Microsoft.VisualStudio.TestTools.UnitTesting;
  691. using SimpleInjector;
  692. using SimpleInjector.Extensions;
  693. public interface ICommandHandler<TCommand>
  694. {
  695. void Handle(TCommand command);
  696. }
  697. public class CustomerMovedCommand
  698. {
  699. [Required]
  700. public int CustomerId { get; set; }
  701. [Required]
  702. public Address Address { get; set; }
  703. }
  704. public class CustomerMovedCommandHandler
  705. : ICommandHandler<CustomerMovedCommand>
  706. {
  707. public void Handle(CustomerMovedCommand command)
  708. {
  709. // some logic
  710. }
  711. }
  712. // Decorator that validates commands before they get executed.
  713. public class ValidatorCommandHandlerDecorator<TCommand>
  714. : ICommandHandler<TCommand>
  715. {
  716. private readonly ICommandHandler<TCommand> decoratedHandler;
  717. private readonly Container container;
  718. public ValidatorCommandHandlerDecorator(
  719. ICommandHandler<TCommand> decoratedHandler,
  720. Container container)
  721. {
  722. this.decoratedHandler = decoratedHandler;
  723. this.container = container;
  724. }
  725. public void Handle(TCommand command)
  726. {
  727. this.Validate(command);
  728. this.decoratedHandler.Handle(command);
  729. }
  730. private void Validate(TCommand command)
  731. {
  732. var validationContext =
  733. new ValidationContext(command, this.container, null);
  734. Validator.ValidateObject(command, validationContext);
  735. }
  736. }
  737. // Decorator that measures the time it takes to execute a command.
  738. public class MonitoringCommandHandlerDecorator<TCommand>
  739. : ICommandHandler<TCommand>
  740. {
  741. private readonly ICommandHandler<TCommand> decoratedHandler;
  742. private readonly ILogger logger;
  743. public MonitoringCommandHandlerDecorator(
  744. ICommandHandler<TCommand> decoratedHandler,
  745. ILogger logger)
  746. {
  747. this.decoratedHandler = decoratedHandler;
  748. this.logger = logger;
  749. }
  750. public void Handle(TCommand command)
  751. {
  752. var watch = Stopwatch.StartNew();
  753. this.decoratedHandler.Handle(command);
  754. this.logger.Log(string.Format("{0} executed in {1} ms.",
  755. command.GetType().Name, watch.ElapsedMilliseconds));
  756. }
  757. }
  758. [TestMethod]
  759. public static void TestRegisterOpenGenericDecorator()
  760. {
  761. // Arrange
  762. var container = new Container();
  763. container.RegisterSingle<ILogger, DebugLogger>();
  764. // Search the given assembly and register all concrete types that
  765. // implement ICommandHandler<TCommand>.
  766. container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
  767. typeof(ICommandHandler<>).Assembly);
  768. // Wrap all ICommandHandler<TCommand> service types with a decorator
  769. // that measures and logs the duration of that handler.
  770. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  771. typeof(MonitoringCommandHandlerDecorator<>));
  772. // Wrap all ICommandHandler<TCommand> types (in this case it will
  773. // wrap the monitoring decorator), but only if the TCommand contains
  774. // any properties.
  775. container.RegisterOpenGenericDecorator(typeof(ICommandHandler<>),
  776. typeof(ValidatorCommandHandlerDecorator<>), c =>
  777. {
  778. var commandType = c.ServiceType.GetGenericArguments()[0];
  779. bool mustDecorate = commandType.GetProperties().Any();
  780. return mustDecorate;
  781. });
  782. // Act
  783. var handler =
  784. container.GetInstance<ICommandHandler<CustomerMovedCommand>>();
  785. // Assert
  786. Assert.IsInstanceOfType(handler,
  787. typeof(ValidatorCommandHandlerDecorator<CustomerMovedCommand>));
  788. }
  789. ]]></code>
  790. </example>
  791. <param name="container">The container to make the registrations in.</param>
  792. <param name="openGenericServiceType">The definition of the open generic service type that will
  793. be wrapped by the given <paramref name="openGenericDecorator"/>.</param>
  794. <param name="openGenericDecorator">The definition of the open generic decorator type that will
  795. be used to wrap the original service type.</param>
  796. <param name="predicate">The predicate that determines whether the
  797. <paramref name="openGenericDecorator"/> must be applied to a service type.</param>
  798. <exception cref="T:System.ArgumentNullException">Thrown when either <paramref name="container"/>,
  799. <paramref name="openGenericServiceType"/>, <paramref name="openGenericDecorator"/>, or
  800. <paramref name="predicate"/> are null references.</exception>
  801. <except

Large files files are truncated, but you can click here to view the full file