You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.6 KiB

2 years ago
  1. //
  2. // Copyright © 2019 Swinject Contributors. All rights reserved.
  3. //
  4. protocol InstanceWrapper {
  5. static var wrappedType: Any.Type { get }
  6. init?(inContainer container: Container, withInstanceFactory factory: (() -> Any?)?)
  7. }
  8. /// Wrapper to enable delayed dependency instantiation.
  9. /// `Lazy<Type>` does not need to be explicitly registered into the `Container` - resolution will work
  10. /// as long as there is a registration for the `Type`.
  11. public final class Lazy<Service>: InstanceWrapper {
  12. static var wrappedType: Any.Type { return Service.self }
  13. private let factory: () -> Any?
  14. private let graphIdentifier: GraphIdentifier?
  15. private weak var container: Container?
  16. init?(inContainer container: Container, withInstanceFactory factory: (() -> Any?)?) {
  17. guard let factory = factory else { return nil }
  18. self.factory = factory
  19. graphIdentifier = container.currentObjectGraph
  20. self.container = container
  21. }
  22. private var _instance: Service?
  23. /// Getter for the wrapped object.
  24. /// It will be resolved from the `Container` when first accessed, all other calls will return the same instance.
  25. public var instance: Service {
  26. if let instance = _instance {
  27. return instance
  28. } else {
  29. _instance = makeInstance()
  30. return _instance!
  31. }
  32. }
  33. private func makeInstance() -> Service? {
  34. guard let container = container else {
  35. return nil
  36. }
  37. if let graphIdentifier = graphIdentifier {
  38. container.restoreObjectGraph(graphIdentifier)
  39. }
  40. return factory() as? Service
  41. }
  42. }
  43. /// Wrapper to enable delayed dependency instantiation.
  44. /// `Provider<Type>` does not need to be explicitly registered into the `Container` - resolution will work
  45. /// as long as there is a registration for the `Type`.
  46. public final class Provider<Service>: InstanceWrapper {
  47. static var wrappedType: Any.Type { return Service.self }
  48. private let factory: () -> Any?
  49. init?(inContainer _: Container, withInstanceFactory factory: (() -> Any?)?) {
  50. guard let factory = factory else { return nil }
  51. self.factory = factory
  52. }
  53. /// Getter for the wrapped object.
  54. /// New instance will be resolved from the `Container` every time it is accessed.
  55. public var instance: Service {
  56. return factory() as! Service
  57. }
  58. }
  59. extension Optional: InstanceWrapper {
  60. static var wrappedType: Any.Type { return Wrapped.self }
  61. init?(inContainer _: Container, withInstanceFactory factory: (() -> Any?)?) {
  62. self = factory?() as? Wrapped
  63. }
  64. }