add methods to EntityState to improve ergonomics

This commit is contained in:
Igor Kravchenko 2020-10-03 23:29:27 +03:00
parent 39692bbfc2
commit 76c91d83f7
3 changed files with 100 additions and 0 deletions

View File

@ -192,6 +192,66 @@ public class EntityState {
}
}
/// This extension provides ergonomic way to add component mapping and component
/// provider at once
extension EntityState {
/// Creates a mapping for the component type to a specific component instance.
/// ComponentInstanceProvider is used for the mapping.
/// - Parameter component: The component instance to use for the mapping
/// - Returns: This EntityState, so more modifications can be applied
@discardableResult
@inline(__always)
public func addInstance<C: ComponentInitializable>(_ component: C) -> Self {
add(C.self).withInstance(component)
return self
}
/// Creates a mapping for the component type to new instances of the provided type.
/// A ComponentTypeProvider is used for the mapping.
/// - Parameter type: The type of components to be created by this mapping
/// - Returns: This EntityState, so more modifications can be applied
@inline(__always)
@discardableResult
public func addType(_ type: ComponentInitializable.Type) -> Self {
add(type).withType(type)
return self
}
/// Creates a mapping for the component type to a single instance of the provided type.
/// The instance is not created until it is first requested.
/// A ComponentSingletonProvider is used for the mapping.
/// - Parameter type: The type of the single instance to be created.
/// - Returns: This EntityState, so more modifications can be applied
@inline(__always)
@discardableResult
public func addSingleton(_ type: ComponentInitializable.Type) -> Self {
add(type).withSingleton(type)
return self
}
/// Creates a mapping for the component type to a method call.
/// A DynamicComponentProvider is used for the mapping.
/// - Parameter method: The method to return the component instance
/// - Returns: This EntityState, so more modifications can be applied
@inline(__always)
@discardableResult
public func addMethod<C: ComponentInitializable>(type: C.Type, closure: DynamicComponentProvider.Closure) -> Self {
add(type).withMethod(closure)
return self
}
/// Creates a mapping for the component type to any ComponentProvider.
/// - Parameter type: The type of component to be mapped
/// - Parameter provider: The component provider to use.
/// - Returns: This EntityState, so more modifications can be applied.
@inline(__always)
@discardableResult
public func addProvider<C: ComponentInitializable>(type: C.Type, provider: ComponentProvider) -> Self {
add(type).withProvider(provider)
return self
}
}
// MARK: -
/// Used by the EntityState class to create the mappings of components to providers via a fluent interface.

View File

@ -270,6 +270,41 @@ class EntityStateTests: XCTestCase {
XCTAssertTrue(state.has(MockComponent.self))
}
func testAddInstanceCreatesMappingAndSetsInstanceProviderForInstanceType() {
let component = MockComponent()
state.addInstance(component)
XCTAssertTrue(state.get(MockComponent.self) is ComponentInstanceProvider?)
XCTAssert(state.get(MockComponent.self)?.getComponent() === component)
}
func testAddTypeCreatesMappingAndSetsTypeProviderForType() {
state.addType(MockComponent.self)
XCTAssertTrue(state.get(MockComponent.self) is ComponentTypeProvider?)
XCTAssertNotNil(state.get(MockComponent.self)?.getComponent())
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() is MockComponent?)
}
func testAddSingletonCreatesMappingAndSetsSingletonProviderForType() {
state.addSingleton(MockComponent.self)
XCTAssertTrue(state.get(MockComponent.self) is ComponentSingletonProvider?)
XCTAssertNotNil(state.get(MockComponent.self)?.getComponent())
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() is MockComponent?)
}
func testAddMethodCreatesMappingAndSetsDynamicProviderForType() {
let component = MockComponent()
state.addMethod(type: MockComponent.self, closure: .init { component })
XCTAssertTrue(state.get(MockComponent.self) is DynamicComponentProvider?)
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() === component)
}
func testAddProviderCreatesMappingAndSetsProvider() {
let provider = ComponentSingletonProvider(type: MockComponent.self)
state.addProvider(type: MockComponent.self, provider: provider)
XCTAssert(state.get(MockComponent.self) is ComponentSingletonProvider?)
XCTAssertNotNil(state.get(MockComponent.self))
}
class MockComponent: ComponentInitializable {
let value: Int

View File

@ -113,6 +113,11 @@ extension EntityStateTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__EntityStateTests = [
("testAddInstanceCreatesMappingAndSetsInstanceProviderForInstanceType", testAddInstanceCreatesMappingAndSetsInstanceProviderForInstanceType),
("testAddMethodCreatesMappingAndSetsDynamicProviderForType", testAddMethodCreatesMappingAndSetsDynamicProviderForType),
("testAddProviderCreatesMappingAndSetsProvider", testAddProviderCreatesMappingAndSetsProvider),
("testAddSingletonCreatesMappingAndSetsSingletonProviderForType", testAddSingletonCreatesMappingAndSetsSingletonProviderForType),
("testAddTypeCreatesMappingAndSetsTypeProviderForType", testAddTypeCreatesMappingAndSetsTypeProviderForType),
("testAddWithInstanceQualifierCreatesInstanceProvider", testAddWithInstanceQualifierCreatesInstanceProvider),
("testAddWithMethodQualifierCreatesDynamicProvider", testAddWithMethodQualifierCreatesDynamicProvider),
("testAddWithNoQualifierCreatesTypeProvider", testAddWithNoQualifierCreatesTypeProvider),