1 /** 2 Provides annotation based configuration and registration for components. 3 4 License: 5 Boost Software License - Version 1.0 - August 17th, 2003 6 7 Permission is hereby granted, free of charge, to any person or organization 8 obtaining a copy of the software and accompanying documentation covered by 9 this license (the "Software") to use, reproduce, display, distribute, 10 execute, and transmit the Software, and to prepare derivative works of the 11 Software, and to permit third-parties to whom the Software is furnished to 12 do so, all subject to the following: 13 14 The copyright notices in the Software and this entire statement, including 15 the above license grant, this restriction and the following disclaimer, 16 must be included in all copies of the Software, in whole or in part, and 17 all derivative works of the Software, unless such copies or derivative 18 works are solely in the form of machine-executable object code generated by 19 a source language processor. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 24 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 25 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 26 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 DEALINGS IN THE SOFTWARE. 28 29 Authors: 30 aermicioi 31 **/ 32 module aermicioi.aedi.configurer.annotation.component_scan; 33 34 import aermicioi.aedi.configurer.annotation.annotation; 35 import aermicioi.aedi.storage.locator; 36 import aermicioi.aedi.storage.storage; 37 import aermicioi.aedi.storage.wrapper; 38 import aermicioi.aedi.container.container; 39 import aermicioi.aedi.factory.factory; 40 import aermicioi.aedi.factory.reference; 41 import aermicioi.aedi.factory.generic_factory; 42 import aermicioi.aedi.factory.proxy_factory; 43 import aermicioi.aedi.exception; 44 import aermicioi.util.traits; 45 import aermicioi.aedi.factory.decorating_factory : WrappingFactory; 46 47 import std.traits; 48 import std.meta; 49 import std.typecons; 50 import std.conv : to; 51 import std.algorithm; 52 53 /** 54 Register an object into storage using annotations provided in it. 55 56 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 57 annotation is found, object is not registered in storage. 58 59 Params: 60 T = type of object to be registered 61 storage = the storage where to register the object 62 locator = the locator used to find object dependencies 63 id = identity by which object will be stored in storage 64 **/ 65 auto componentScan(T)(Storage!(ObjectFactory, string) storage, Locator!() locator, string id) { 66 auto factory = componentScanImpl!T(locator); 67 68 alias SubComponents = staticMap!( 69 partialPrefixed!( 70 getMember, 71 T 72 ), 73 Filter!( 74 templateAnd!( 75 partialPrefixed!( 76 partialSuffixed!( 77 isProtection, 78 "public" 79 ), 80 T 81 ), 82 chain!( 83 isType, 84 partialPrefixed!( 85 getMember, 86 T 87 ) 88 ), 89 chain!( 90 isClass, 91 partialPrefixed!( 92 getMember, 93 T 94 ) 95 ) 96 ), 97 __traits(allMembers, T) 98 ) 99 ); 100 101 static if (SubComponents.length > 0) { 102 storage.componentScan!SubComponents(locator); 103 } 104 105 if (factory !is null) { 106 storage.set(new WrappingFactory!(Factory!T)(factory), id); 107 } 108 109 return storage; 110 } 111 112 /** 113 Register an object into storage by it's type FQN using annotations provided in it. 114 115 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 116 annotation is found, object is not registered in storage. 117 118 Params: 119 T = type of object to be registered 120 storage = the storage where to register the object 121 **/ 122 auto componentScan(T)(Storage!(ObjectFactory, string) storage, Locator!() locator) { 123 124 alias qualifiers = Filter!(isQualifier, allUDAs!T); 125 126 static if (qualifiers.length > 0) { 127 return storage.componentScan!T(locator, qualifiers[0].id); 128 } else { 129 return storage.componentScan!T(locator, name!T); 130 } 131 } 132 133 /** 134 ditto 135 **/ 136 auto componentScan(T)(ConfigurableContainer storage) { 137 138 return storage.componentScan!T(storage); 139 } 140 141 /** 142 Register an object into storage by I's interface FQN that it implements using annotations provided in it. 143 144 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 145 annotation is found, object is not registered in storage. 146 147 Params: 148 I = the inteface that object implements. 149 T = type of object to be registered 150 storage = the storage where to register the object 151 **/ 152 auto componentScan(I, T)(Storage!(ObjectFactory, string) storage, Locator!() locator) 153 if (is(I == interface) && is(T == class) && is(T : I)) { 154 155 alias qualifiers = Filter!( 156 isQualifier, 157 allUDAs!I 158 ); 159 160 static if (qualifiers.length > 0) { 161 return storage.componentScan!T(locator, qualifier[0].id); 162 } else { 163 return storage.componentScan!T(locator, name!I); 164 } 165 } 166 167 /** 168 ditto 169 **/ 170 auto componentScan(I, T)(ConfigurableContainer storage) 171 if (is(I == interface) && is(T == class) && is(T : I)) { 172 173 return storage.componentScan!(I, T)(storage); 174 } 175 176 /** 177 Register a set of objects by it's type, or implemented interface into a storage. 178 179 When registering an object by it's interface, next to interface it is required to specify the original type of object. 180 Note: An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 181 annotation is found, object is not registered in storage. 182 183 Params: 184 I = the inteface that object implements. 185 T = type of object to be registered 186 storage = the storage where to register the object 187 **/ 188 auto componentScan(T, V...)(Storage!(ObjectFactory, string) storage, Locator!() locator) { 189 storage.componentScan!T(locator); 190 191 return storage.componentScan!V(locator); 192 } 193 194 /** 195 ditto 196 **/ 197 auto componentScan(T, V...)(ConfigurableContainer storage) { 198 199 return storage.componentScan!(T, V)(storage); 200 } 201 202 /** 203 ditto 204 **/ 205 auto componentScan(I, T, V...)(Storage!(ObjectFactory, string) storage, Locator!() locator) 206 if (is(I == interface) && is(T == class) && is(T : I)) { 207 storage.componentScan!(I, T)(locator); 208 209 return storage.componentScan!(V)(locator); 210 } 211 212 /** 213 ditto 214 **/ 215 auto componentScan(I, T, V...)(ConfigurableContainer storage) 216 if (is(I == interface) && is(T == class) && is(T : I)) { 217 218 return storage.componentScan!(I, T, V)(storage); 219 } 220 221 /** 222 Scan a module and register all public objects that are annotated with @component annotation. 223 224 Note: An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 225 annotation is found, object is not registered in storage. 226 227 Params: 228 Module = module to scan for components. 229 storage = the storage where to register the object 230 locator = the locator used to fetch registered object's dependencies. 231 **/ 232 auto componentScan(alias Module)(Storage!(ObjectFactory, string) storage, Locator!() locator) 233 if (startsWith(Module.stringof, "module ")) { 234 235 alias components = staticMap!( 236 partialPrefixed!( 237 getMember, 238 Module 239 ), 240 Filter!( 241 templateAnd!( 242 partialSuffixed!( 243 partialPrefixed!( 244 isProtection, 245 Module 246 ), 247 "public" 248 ), 249 chain!( 250 isType, 251 partialPrefixed!( 252 getMember, 253 Module 254 ) 255 ), 256 chain!( 257 isClass, 258 partialPrefixed!( 259 getMember, 260 Module 261 ) 262 ) 263 ), 264 __traits(allMembers, Module) 265 ) 266 ); 267 268 storage.componentScan!components(locator); 269 270 return storage; 271 } 272 273 /** 274 ditto 275 **/ 276 auto componentScan(alias M)(ConfigurableContainer storage) 277 if (startsWith(M.stringof, "module")) { 278 279 return storage.componentScan!(M)(storage); 280 } 281 282 /** 283 Scan a set of modules and register all public objects that are annotated with @component annotation. 284 285 Due to limitations of D language currently it is impossible to recursively scan all public imports of a module to register all 286 depencies of a package. Each particular module should be specified in order to register dependencies. 287 Note: An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 288 annotation is found, object is not registered in storage. 289 290 Params: 291 M = current module to scan. 292 V = rest set of modules waiting for scan. 293 storage = the storage where to register the object 294 locator = the locator used to fetch registered object's dependencies. 295 **/ 296 auto componentScan(alias M, V...)(Storage!(ObjectFactory, string) storage, Locator!() locator) 297 if (startsWith(M.stringof, "module")) { 298 storage.componentScan!M(locator); 299 return storage.componentScan!V(locator); 300 } 301 302 /** 303 ditto 304 **/ 305 auto componentScan(alias M, V...)(ConfigurableContainer storage) 306 if (startsWith(M.stringof, "module")) { 307 308 return storage.componentScan!(M, V)(storage); 309 } 310 311 /** 312 Register an object into a storage contained in storageLocator and identified by @container annotation using annotations provided in it. 313 314 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 315 annotation is found, object is not registered in storage. 316 317 Params: 318 T = type of object to be registered 319 storageLocator = the locator from which to fetch storage for object 320 locator = locator used to find dependencies for object 321 id = identity by which object will be stored in storage 322 **/ 323 auto componentScan(T, R : Locator!())(R storageLocator, Locator!() locator, string id) 324 if (!is(R : Storage!(ObjectFactory, string))) { 325 326 alias containers = Filter!( 327 isContained, 328 allUDAs!T 329 ); 330 331 static if (containers.length > 0) { 332 string storageId = containers[0].id; 333 } else { 334 string storageId = "singleton"; 335 } 336 337 auto storage = storageLocator.locate!(Storage!(ObjectFactory, string))(storageId); 338 339 if (storage !is null) { 340 341 storage.componentScan!T(locator, id); 342 } else { 343 344 throw new NotFoundException("Could not find storage to save factory for object of identity " ~ id); 345 } 346 347 return storageLocator; 348 } 349 350 /** 351 ditto 352 **/ 353 auto componentScan(T, R : Locator!())(R locator, string id) 354 if (!is(R : Storage!(ObjectFactory, string))) { 355 return locator.componentScan!T(locator, id); 356 } 357 358 /** 359 ditto 360 **/ 361 auto componentScan(T, R : Locator!())(R storageLocator, Locator!() locator) 362 if (!is(R : Storage!(ObjectFactory, string))) { 363 364 alias qualifiers = Filter!( 365 isQualifier, 366 allUDAs!T 367 ); 368 369 static if (qualifiers.length > 0) { 370 return storageLocator.componentScan!T(locator, qualifiers[0].id); 371 } else { 372 return storageLocator.componentScan!T(locator, name!T); 373 } 374 } 375 376 /** 377 ditto 378 **/ 379 auto componentScan(T, R : Locator!())(R locator) 380 if (!is(R : Storage!(ObjectFactory, string))) { 381 return locator.componentScan!T(locator); 382 } 383 384 /** 385 ditto 386 **/ 387 template componentScan(T, V...) 388 if((V.length > 0)) { 389 390 /** 391 ditto 392 **/ 393 auto componentScan(R : Locator!())(R storageLocator, Locator!() locator) 394 if (!is(R : Storage!(ObjectFactory, string))) { 395 .componentScan!T(storageLocator, locator); 396 397 return .componentScan!V(storageLocator, locator); 398 } 399 400 /** 401 ditto 402 **/ 403 auto componentScan(R : Locator!())(R locator) 404 if (!is(R : Storage!(ObjectFactory, string))) { 405 .componentScan!T(locator, locator); 406 407 return .componentScan!V(locator, locator); 408 } 409 } 410 411 /** 412 Register an object into a storage contained in storageLocator and identified by @container annotation using annotations provided in it. 413 414 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 415 annotation is found, object is not registered in storage. 416 417 Params: 418 I = interface implemented by object, by which to register it. 419 T = type of object to be registered 420 storageLocator = locator used to find storage for object 421 locator = locator used to find dependencies for object 422 **/ 423 auto componentScan(I, T, R : Locator!())(R storageLocator, Locator!() locator) 424 if (is (I == interface) && is (T == class) && is (T : I) && !is(R : Storage!(ObjectFactory, string))) { 425 alias qualifiers = Filter!( 426 isQualifier, 427 allUDAs!I 428 ); 429 430 static if (qualifiers.length > 0) { 431 return storageLocator.componentScan!T(locator, qualifiers[0].id); 432 } else { 433 return storageLocator.componentScan!T(locator, name!I); 434 } 435 } 436 437 /** 438 ditto 439 **/ 440 auto componentScan(I, T, R : Locator!())(R locator) 441 if (is (I == interface) && is (T == class) && is (T : I) && !is(R : Storage!(ObjectFactory, string))) { 442 443 return locator.componentScan!(I, T)(locator); 444 } 445 446 /** 447 ditto 448 **/ 449 template componentScan(I, T, V...) 450 if (is (I == interface) && is (T == class) && is (T : I) && (V.length > 0)) { 451 452 /** 453 ditto 454 **/ 455 auto componentScan(R : Locator!())(R storageLocator, Locator!() locator) 456 if (!is(R : Storage!(ObjectFactory, string))) { 457 458 .componentScan!(I, T)(storageLocator, locator); 459 460 return .componentScan!(V)(storageLocator, locator); 461 } 462 463 /** 464 ditto 465 **/ 466 auto componentScan(R : Locator!())(R locator) 467 if (!is(R : Storage!(ObjectFactory, string))) { 468 469 .componentScan!(I, T)(locator); 470 471 return .componentScan!(V)(locator); 472 } 473 } 474 475 /** 476 Register module's objects into a storage contained in storageLocator and identified by @container annotation using annotations provided in it. 477 478 An object will be registered in storage only in case when it is annotated with @component annotation. In case when no @component 479 annotation is found, object is not registered in storage. 480 481 Params: 482 M = module to scan for instantiable objects. 483 storageLocator = locator used to find storage for objects 484 locator = locator used to find object dependencies 485 **/ 486 auto componentScan(alias M, R : Locator!())(R storageLocator, Locator!() locator) 487 if (M.stringof.startsWith("module ") && !is(R : Storage!(ObjectFactory, string))) { 488 489 alias components = getPossibleComponents!M; 490 491 storageLocator.componentScan!components(locator); 492 493 return storageLocator; 494 } 495 496 /** 497 ditto 498 **/ 499 auto componentScan(alias M, R : Locator!())(R locator) 500 if (M.stringof.startsWith("module ") && !is(R : Storage!(ObjectFactory, string))) { 501 502 locator.componentScan!M(locator); 503 504 return locator; 505 } 506 507 /** 508 ditto 509 **/ 510 template componentScan(alias M, V...) 511 if (M.stringof.startsWith("module ") && (V.length > 0)) { 512 513 /** 514 ditto 515 **/ 516 auto componentScan(R : Locator!())(R locatorStorage, Locator!() locator) 517 if (!is(R : Storage!(ObjectFactory, string))) { 518 519 .componentScan!M(locatorStorage, locator); 520 return .componentScan!V(locatorStorage, locator); 521 } 522 523 /** 524 ditto 525 **/ 526 auto componentScan(R : Locator!())(R locator) 527 if (!is(R : Storage!(ObjectFactory, string))) { 528 529 .componentScan!M(locator); 530 return .componentScan!V(locator); 531 } 532 } 533 534 /** 535 Checks if a structure has factory method for GenericFactory. 536 537 This static interface is used by annotation system to identify annotations that mark an object as instantiable by container. 538 The @component annotation is such a structure that implements this static interface and therefore it is possible to use it to 539 mark components instantiable. A "@component" annotation must have a factory method that returns a GenericFactory instance that 540 further will be used to configure an instantiable object. In such a way it is possbile to define other custom annotations that 541 return GenericFactory implementations that add/or behave differrently comparing to default implementation of GenericFactory. 542 543 Examples: 544 -------------------- 545 struct Component { 546 GenericFactory!T factory(T)(Locator!() locator) { 547 return new GenericFactoryImpl!(T)(locator); 548 } 549 } 550 -------------------- 551 Params: 552 T = the structure to be tested for interface compatibility 553 Z = the type of object that T has to instantiate 554 555 Returns: 556 true in case of structure implementing static interface, false otherwise. 557 **/ 558 template canFactoryGenericFactory(alias T, Z) 559 if (!isTemplate!T) { 560 alias canFactoryGenericFactory = canFactoryGenericFactory!(typeof(T), Z); 561 } 562 563 /** 564 ditto 565 **/ 566 template canFactoryGenericFactory(T, Z) 567 if (isAggregateType!T) { 568 569 static if (hasMember!(T, "factory")) { 570 alias factory = getMember!(T, "factory"); 571 572 alias checker = templateOr!( 573 chain!( 574 partialPrefixed!( 575 isDerived, 576 ReturnType!(factory!Z) 577 ), 578 chain!( 579 GenericFactory, 580 Wrapper 581 ) 582 ), 583 chain!( 584 partialPrefixed!( 585 isDerived, 586 ReturnType!(factory!Z) 587 ), 588 GenericFactory 589 ) 590 ); 591 enum bool canFactoryGenericFactory = checker!Z; 592 } else { 593 594 enum bool canFactoryGenericFactory = false; 595 } 596 } 597 598 /** 599 Checks if a structure has factoryContainer method for InstanceFactory. 600 601 This static interface is used to find annotations that can provide a InstanceFactory for GenericFactory to be used by it to instantiate 602 the object. The @constructor annotation implements this annotation and therefore it is possible to use it to mark a constructor to be used 603 for object construction. Any annotation implementing this interface can be used by annotation system to configure objects. 604 605 Examples: 606 -------------------- 607 struct SetterAnnotation(Args...) { 608 Tuple!Args args; 609 610 this(Args args) { 611 this.args = args; 612 } 613 614 InstanceFactory!T factoryContainer(T, string property)(Locator!() locator) { 615 auto constructor = new ConstructorBasedFactory!(T, Args)(args.expand); 616 constructor.locator = locator; 617 618 return constructor; 619 620 } 621 } 622 -------------------- 623 Params: 624 T = the structure to be tested for interface compatibility 625 Z = the type of object that T has to instantiate 626 627 Returns: 628 true in case of structure implementing static interface, false otherwise. 629 **/ 630 template canFactoryInstanceFactory(alias T, Z, string property = "__ctor") { 631 alias canFactoryInstanceFactory = canFactoryInstanceFactory!(typeof(T), Z, property); 632 } 633 634 /** 635 ditto 636 **/ 637 template canFactoryInstanceFactory(T, Z, string property = "__ctor") { 638 static if (hasMember!(T, "factoryContainer")) { 639 alias factory = getMember!(T, "factoryContainer"); 640 641 alias checker = templateOr!( 642 chain!( 643 partialPrefixed!( 644 isDerived, 645 ReturnType!(factory!(Z, property)) 646 ), 647 chain!( 648 InstanceFactory, 649 Wrapper 650 ) 651 ), 652 chain!( 653 partialPrefixed!( 654 isDerived, 655 ReturnType!(factory!(Z, property)) 656 ), 657 InstanceFactory 658 ) 659 ); 660 enum bool canFactoryInstanceFactory = checker!Z; 661 } else { 662 663 enum bool canFactoryInstanceFactory = false; 664 } 665 } 666 667 /** 668 Checks if a structure has factoryConfigurer method for PropertyConfigurer. 669 670 This static interface is used to find annotations that can provide a PropertyConfigurer for GenericFactory to be used by it to configure 671 the object. The @setter annotation implements this annotation and therefore it is possible to use it to mark a setter to be used 672 for object construction. Any annotation implementing this interface can be used by annotation system to configure objects. 673 674 Examples: 675 -------------------- 676 struct Setter(Args...) { 677 Tuple!Args args; 678 679 this(Args args) { 680 this.args = args; 681 } 682 683 PropertyConfigurer!T factoryConfigurer(T, string method)(Locator!() locator) { 684 auto method = new MethodConfigurer!(T, method, Args)(args.expand); 685 method.locator = locator; 686 687 return method; 688 } 689 } 690 -------------------- 691 Params: 692 T = the structure to be tested for interface compatibility 693 Z = the type of object that T has to call T's property method 694 property = the method of Z that T has to call 695 Returns: 696 true in case of structure implementing static interface, false otherwise. 697 **/ 698 template canFactoryPropertyConfigurer(alias T, Z, string property = "") { 699 alias canFactoryPropertyConfigurer = canFactoryPropertyConfigurer!(typeof(T), Z, property); 700 } 701 702 /** 703 ditto 704 **/ 705 template canFactoryPropertyConfigurer(T, Z, string property = "") { 706 static if (hasMember!(T, "factoryConfigurer")) { 707 alias factory = getMember!(T, "factoryConfigurer"); 708 709 alias checker = templateOr!( 710 chain!( 711 partialPrefixed!( 712 isDerived, 713 ReturnType!(factory!(Z, property)) 714 ), 715 chain!( 716 PropertyConfigurer, 717 Wrapper 718 ) 719 ), 720 chain!( 721 partialPrefixed!( 722 isDerived, 723 ReturnType!(factory!(Z, property)) 724 ), 725 PropertyConfigurer 726 ) 727 ); 728 enum bool canFactoryPropertyConfigurer = checker!Z; 729 } else { 730 731 enum bool canFactoryPropertyConfigurer = false; 732 } 733 } 734 735 public auto componentScanImpl(T)(Locator!() locator) { 736 debug { 737 pragma(msg, "Scanning ", fullyQualifiedName!T); 738 } 739 740 alias Components = Filter!( 741 partialSuffixed!( 742 canFactoryGenericFactory, 743 T 744 ), 745 allUDAs!T 746 ); 747 748 static if (Components.length > 0) { 749 auto factory = toValue!(Components[0]).factory!T(locator); 750 751 debug { 752 pragma(msg, "Found component"); 753 } 754 755 alias constructorUdas = Filter!( 756 partialSuffixed!( 757 canFactoryInstanceFactory, 758 T 759 ), 760 allUDAs!T 761 ); 762 763 alias configurerUdas = Filter!( 764 partialSuffixed!( 765 canFactoryPropertyConfigurer, 766 T 767 ), 768 allUDAs!T 769 ); 770 771 foreach (configurer; tuple(staticMap!(toValue, configurerUdas))) { 772 debug { 773 pragma(msg, "Found configurer ", name!configurer, " on ", name!T, " declaration"); 774 } 775 776 factory.addPropertyConfigurer(configurer.factoryConfigurer!(T, "")(locator)); 777 } 778 779 static if (constructorUdas.length > 0) { 780 debug { 781 pragma(msg, "Found constructor right on ", name!T); 782 } 783 784 factory.setInstanceFactory(toValue!(constructorUdas[0]).factoryContainer!(T, name!T)(locator)); 785 } else { 786 alias instantiatorHolders = Filter!( 787 templateAnd!( 788 partialSuffixed!( 789 partialPrefixed!( 790 isProtection, 791 T 792 ), 793 "public" 794 ), 795 eq!"__ctor", 796 chain!( 797 isSomeFunction, 798 partialPrefixed!( 799 getMember, 800 T 801 ) 802 ) 803 ), 804 __traits(allMembers, T) 805 ); 806 807 foreach (instantiatorHolder; instantiatorHolders) { 808 foreach (overload; __traits(getOverloads, T, instantiatorHolder)) { 809 alias udas = Filter!( 810 partialSuffixed!( 811 canFactoryInstanceFactory, 812 T 813 ), 814 allUDAs!overload 815 ); 816 817 static if (udas.length > 0) { 818 debug { 819 pragma(msg, "Found custom constructor for ", name!T, " on ", instantiatorHolder, " with arguments ", Parameters!overload); 820 } 821 822 factory.setInstanceFactory(toValue!(udas[0]).factoryContainer!(T, instantiatorHolder)(locator)); 823 } 824 } 825 } 826 } 827 828 alias configurerHolders = Filter!( 829 templateAnd!( 830 partialSuffixed!( 831 partialPrefixed!( 832 isProtection, 833 T 834 ), 835 "public" 836 ), 837 templateNot!(eq!"__ctor") 838 ), 839 __traits(allMembers, T) 840 ); 841 842 foreach (member; configurerHolders) { 843 844 static if (isSomeFunction!(getMember!(T, member))) { 845 foreach (overload; __traits(getOverloads, T, member)) { 846 alias udas = Filter!( 847 partialSuffixed!( 848 canFactoryPropertyConfigurer, 849 T, 850 member 851 ), 852 allUDAs!overload 853 ); 854 855 foreach (uda; tuple(staticMap!(toValue, udas))) { 856 debug { 857 pragma(msg, "Found configurer ", name!uda, " for ", name!T, "'s method ", member); 858 } 859 860 factory.addPropertyConfigurer(uda.factoryConfigurer!(T, member)(locator)); 861 } 862 } 863 } else static if (isField!(T, member)) { 864 865 alias udas = Filter!( 866 partialSuffixed!( 867 canFactoryPropertyConfigurer, 868 T, 869 member 870 ), 871 allUDAs!(getMember!(T, member)) 872 ); 873 874 foreach (uda; tuple(staticMap!(toValue, udas))) { 875 debug { 876 pragma(msg, "Found configurer ", name!uda, " for ", name!T, "'s field ", member); 877 } 878 879 factory.addPropertyConfigurer(uda.factoryConfigurer!(T, member)(locator)); 880 } 881 } 882 } 883 884 return factory; 885 } else { 886 debug { 887 pragma(msg, "Not a component"); 888 } 889 890 return null; 891 } 892 } 893 894 private template isQualifier(alias T) { 895 alias isQualifier = isQualifier!(typeof(T)); 896 } 897 898 private template isQualifier(T) { 899 enum bool isQualifier = is(T == QualifierAnnotation); 900 } 901 902 private template isContained(alias T) { 903 alias isContained = isContained!(typeof(T)); 904 } 905 906 private template isContained(T) { 907 enum bool isContained = is(T == ContainedAnnotation); 908 } 909 910 private template isValue(T) { 911 enum bool isValue = is (typeof(T)); 912 } 913 914 private template isReturnTypeEq(alias symbol, Type) 915 if (isSomeFunction!symbol) { 916 enum bool isReturnTypeEq = is(ReturnType!symbol : Type); 917 } 918 919 private template isNamedTemplate(alias T, string name) { 920 enum bool isNamedTemplate = isTemplate!T && (identifier!T == name); 921 } 922 923 private template isEqByFQDN(alias first, alias second) { 924 enum bool isEqByFQDN = fullyQualifiedName!first == fullyQualifiedName!second; 925 } 926 927 private template instantiatonToTemplate(alias T, alias Template = T) { 928 static if (isTemplateInstantiationOf!(T, Template)) { 929 alias instantiatonToTemplate = Template; 930 } else static if (isTemplate!T) { 931 alias instantiatonToTemplate = T; 932 } 933 } 934 935 private enum bool isTemplateInstantiationOf(T, alias Template) = is(T : Template!(Z), Z...); 936 private enum bool isTemplateInstantiationOf(alias T, alias Template) = is(typeof(T) : Template!(Z), Z...); 937 938 private template identifierEq(alias T, string identity) { 939 enum bool identifierEq = identifier!T == identity; 940 } 941 942 private template allUDAs(alias symbol) { 943 alias allUDAs = AliasSeq!(__traits(getAttributes, symbol)); 944 } 945 946 private template toValue(T) { 947 enum auto toValue = T(); 948 } 949 950 private template toValue(alias T) { 951 alias toValue = T; 952 } 953 954 private template isType(alias T) { 955 static if (__traits(compiles, () { T z = T.init; })) { 956 957 enum bool isType = true; 958 } else { 959 960 enum bool isType = false; 961 } 962 } 963 964 private template isClass(alias T) { 965 enum bool isClass = is(typeof(T) == class); 966 } 967 968 private template isClass(T) { 969 enum bool isClass = is(T == class); 970 } 971 972 private template isStruct(alias T) { 973 enum bool isStruct = is(typeof(T) == struct); 974 } 975 976 private template isStruct(T) { 977 enum bool isStruct = is(T == struct); 978 } 979 980 private template getPublicAggregateMembers(alias Symbol) { 981 alias getPublicAggregateMembers = Filter!( 982 templateAnd!( 983 partialSuffixed!( 984 partialPrefixed!( 985 isProtection, 986 Symbol 987 ), 988 "public" 989 ), 990 chain!( 991 hasMembers, 992 partialPrefixed!( 993 getMember, 994 Symbol 995 ) 996 ) 997 ), 998 __traits(allMembers, Symbol) 999 ); 1000 } 1001 1002 private template getPossibleComponents(alias Symbol) { 1003 alias getPossibleComponents = staticMap!( 1004 partialPrefixed!( 1005 getMember, 1006 Symbol 1007 ), 1008 Filter!( 1009 templateAnd!( 1010 partialSuffixed!( 1011 partialPrefixed!( 1012 isProtection, 1013 Symbol 1014 ), 1015 "public" 1016 ), 1017 chain!( 1018 isType, 1019 partialPrefixed!( 1020 getMember, 1021 Symbol 1022 ) 1023 ), 1024 chain!( 1025 templateOr!( 1026 isClass, 1027 isStruct 1028 ), 1029 partialPrefixed!( 1030 getMember, 1031 Symbol 1032 ) 1033 ) 1034 ), 1035 __traits(allMembers, Symbol) 1036 ) 1037 ); 1038 }