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.wrapping_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 // enum bool canFactoryGenericFactory = false; 569 // } 570 571 /** 572 ditto 573 **/ 574 template canFactoryGenericFactory(T, Z) 575 if (isAggregateType!T) { 576 577 static if (hasMember!(T, "factory")) { 578 alias factory = getMember!(T, "factory"); 579 580 alias checker = templateOr!( 581 chain!( 582 partialPrefixed!( 583 isDerived, 584 ReturnType!(factory!Z) 585 ), 586 chain!( 587 GenericFactory, 588 Wrapper 589 ) 590 ), 591 chain!( 592 partialPrefixed!( 593 isDerived, 594 ReturnType!(factory!Z) 595 ), 596 GenericFactory 597 ) 598 ); 599 enum bool canFactoryGenericFactory = checker!Z; 600 } else { 601 602 enum bool canFactoryGenericFactory = false; 603 } 604 } 605 606 /** 607 Checks if a structure has factoryContainer method for InstanceFactory. 608 609 This static interface is used to find annotations that can provide a InstanceFactory for GenericFactory to be used by it to instantiate 610 the object. The @constructor annotation implements this annotation and therefore it is possible to use it to mark a constructor to be used 611 for object construction. Any annotation implementing this interface can be used by annotation system to configure objects. 612 613 Examples: 614 -------------------- 615 struct SetterAnnotation(Args...) { 616 Tuple!Args args; 617 618 this(Args args) { 619 this.args = args; 620 } 621 622 InstanceFactory!T factoryContainer(T, string property)(Locator!() locator) { 623 auto constructor = new ConstructorBasedFactory!(T, Args)(args.expand); 624 constructor.locator = locator; 625 626 return constructor; 627 628 } 629 } 630 -------------------- 631 Params: 632 T = the structure to be tested for interface compatibility 633 Z = the type of object that T has to instantiate 634 635 Returns: 636 true in case of structure implementing static interface, false otherwise. 637 **/ 638 template canFactoryInstanceFactory(alias T, Z, string property = "__ctor") { 639 alias canFactoryInstanceFactory = canFactoryInstanceFactory!(typeof(T), Z, property); 640 } 641 642 /** 643 ditto 644 **/ 645 template canFactoryInstanceFactory(T, Z, string property = "__ctor") { 646 static if (hasMember!(T, "factoryContainer")) { 647 alias factory = getMember!(T, "factoryContainer"); 648 649 alias checker = templateOr!( 650 chain!( 651 partialPrefixed!( 652 isDerived, 653 ReturnType!(factory!(Z, property)) 654 ), 655 chain!( 656 InstanceFactory, 657 Wrapper 658 ) 659 ), 660 chain!( 661 partialPrefixed!( 662 isDerived, 663 ReturnType!(factory!(Z, property)) 664 ), 665 InstanceFactory 666 ) 667 ); 668 enum bool canFactoryInstanceFactory = checker!Z; 669 } else { 670 671 enum bool canFactoryInstanceFactory = false; 672 } 673 } 674 675 /** 676 Checks if a structure has factoryConfigurer method for PropertyConfigurer. 677 678 This static interface is used to find annotations that can provide a PropertyConfigurer for GenericFactory to be used by it to configure 679 the object. The @setter annotation implements this annotation and therefore it is possible to use it to mark a setter to be used 680 for object construction. Any annotation implementing this interface can be used by annotation system to configure objects. 681 682 Examples: 683 -------------------- 684 struct Setter(Args...) { 685 Tuple!Args args; 686 687 this(Args args) { 688 this.args = args; 689 } 690 691 PropertyConfigurer!T factoryConfigurer(T, string method)(Locator!() locator) { 692 auto method = new MethodConfigurer!(T, method, Args)(args.expand); 693 method.locator = locator; 694 695 return method; 696 } 697 } 698 -------------------- 699 Params: 700 T = the structure to be tested for interface compatibility 701 Z = the type of object that T has to call T's property method 702 property = the method of Z that T has to call 703 Returns: 704 true in case of structure implementing static interface, false otherwise. 705 **/ 706 template canFactoryPropertyConfigurer(alias T, Z, string property = "") { 707 alias canFactoryPropertyConfigurer = canFactoryPropertyConfigurer!(typeof(T), Z, property); 708 } 709 710 /** 711 ditto 712 **/ 713 template canFactoryPropertyConfigurer(T, Z, string property = "") { 714 static if (hasMember!(T, "factoryConfigurer")) { 715 alias factory = getMember!(T, "factoryConfigurer"); 716 717 alias checker = templateOr!( 718 chain!( 719 partialPrefixed!( 720 isDerived, 721 ReturnType!(factory!(Z, property)) 722 ), 723 chain!( 724 PropertyConfigurer, 725 Wrapper 726 ) 727 ), 728 chain!( 729 partialPrefixed!( 730 isDerived, 731 ReturnType!(factory!(Z, property)) 732 ), 733 PropertyConfigurer 734 ) 735 ); 736 enum bool canFactoryPropertyConfigurer = checker!Z; 737 } else { 738 739 enum bool canFactoryPropertyConfigurer = false; 740 } 741 } 742 743 public auto componentScanImpl(T)(Locator!() locator) { 744 debug(compileTimeDebug) { 745 pragma(msg, "Scanning ", fullyQualifiedName!T); 746 } 747 748 alias Components = Filter!( 749 partialSuffixed!( 750 canFactoryGenericFactory, 751 T 752 ), 753 allUDAs!T 754 ); 755 756 static if (Components.length > 0) { 757 auto factory = toValue!(Components[0]).factory!T(locator); 758 759 debug(compileTimeDebug) { 760 pragma(msg, "Found component"); 761 } 762 763 alias constructorUdas = Filter!( 764 partialSuffixed!( 765 canFactoryInstanceFactory, 766 T 767 ), 768 allUDAs!T 769 ); 770 771 alias configurerUdas = Filter!( 772 partialSuffixed!( 773 canFactoryPropertyConfigurer, 774 T 775 ), 776 allUDAs!T 777 ); 778 779 foreach (configurer; tuple(staticMap!(toValue, configurerUdas))) { 780 debug(compileTimeDebug) { 781 pragma(msg, "Found configurer ", name!configurer, " on ", name!T, " declaration"); 782 } 783 784 factory.addPropertyConfigurer(configurer.factoryConfigurer!(T, "")(locator)); 785 } 786 787 static if (constructorUdas.length > 0) { 788 debug(compileTimeDebug) { 789 pragma(msg, "Found constructor right on ", name!T); 790 } 791 792 factory.setInstanceFactory(toValue!(constructorUdas[0]).factoryContainer!(T, name!T)(locator)); 793 } else { 794 alias instantiatorHolders = Filter!( 795 templateAnd!( 796 partialSuffixed!( 797 partialPrefixed!( 798 isProtection, 799 T 800 ), 801 "public" 802 ), 803 eq!"__ctor", 804 chain!( 805 isSomeFunction, 806 partialPrefixed!( 807 getMember, 808 T 809 ) 810 ) 811 ), 812 __traits(allMembers, T) 813 ); 814 815 foreach (instantiatorHolder; instantiatorHolders) { 816 foreach (overload; __traits(getOverloads, T, instantiatorHolder)) { 817 alias udas = Filter!( 818 partialSuffixed!( 819 canFactoryInstanceFactory, 820 T 821 ), 822 allUDAs!overload 823 ); 824 825 static if (udas.length > 0) { 826 debug(compileTimeDebug) { 827 pragma(msg, "Found custom constructor for ", name!T, " on ", instantiatorHolder, " with arguments ", Parameters!overload); 828 } 829 830 factory.setInstanceFactory(toValue!(udas[0]).factoryContainer!(T, instantiatorHolder)(locator)); 831 } 832 } 833 } 834 } 835 836 alias configurerHolders = Filter!( 837 templateAnd!( 838 partialSuffixed!( 839 partialPrefixed!( 840 isProtection, 841 T 842 ), 843 "public" 844 ), 845 templateNot!(eq!"__ctor") 846 ), 847 __traits(allMembers, T) 848 ); 849 850 foreach (member; configurerHolders) { 851 852 static if (isSomeFunction!(getMember!(T, member))) { 853 foreach (overload; __traits(getOverloads, T, member)) { 854 alias udas = Filter!( 855 partialSuffixed!( 856 canFactoryPropertyConfigurer, 857 T, 858 member 859 ), 860 allUDAs!overload 861 ); 862 863 foreach (uda; tuple(staticMap!(toValue, udas))) { 864 debug(compileTimeDebug) { 865 pragma(msg, "Found configurer ", name!uda, " for ", name!T, "'s method ", member); 866 } 867 868 factory.addPropertyConfigurer(uda.factoryConfigurer!(T, member)(locator)); 869 } 870 } 871 } else static if (isField!(T, member)) { 872 873 alias udas = Filter!( 874 partialSuffixed!( 875 canFactoryPropertyConfigurer, 876 T, 877 member 878 ), 879 allUDAs!(getMember!(T, member)) 880 ); 881 882 foreach (uda; tuple(staticMap!(toValue, udas))) { 883 debug(compileTimeDebug) { 884 pragma(msg, "Found configurer ", name!uda, " for ", name!T, "'s field ", member); 885 } 886 887 factory.addPropertyConfigurer(uda.factoryConfigurer!(T, member)(locator)); 888 } 889 } 890 } 891 892 return factory; 893 } else { 894 debug(compileTimeDebug) { 895 pragma(msg, "Not a component"); 896 } 897 898 return null; 899 } 900 } 901 902 private template isQualifier(alias T) { 903 alias isQualifier = isQualifier!(typeof(T)); 904 } 905 906 private template isQualifier(T) { 907 enum bool isQualifier = is(T == QualifierAnnotation); 908 } 909 910 private template isContained(alias T) { 911 alias isContained = isContained!(typeof(T)); 912 } 913 914 private template isContained(T) { 915 enum bool isContained = is(T == ContainedAnnotation); 916 } 917 918 private template isValue(T) { 919 enum bool isValue = is (typeof(T)); 920 } 921 922 private template isReturnTypeEq(alias symbol, Type) 923 if (isSomeFunction!symbol) { 924 enum bool isReturnTypeEq = is(ReturnType!symbol : Type); 925 } 926 927 private template isNamedTemplate(alias T, string name) { 928 enum bool isNamedTemplate = isTemplate!T && (identifier!T == name); 929 } 930 931 private template isEqByFQDN(alias first, alias second) { 932 enum bool isEqByFQDN = fullyQualifiedName!first == fullyQualifiedName!second; 933 } 934 935 private template instantiatonToTemplate(alias T, alias Template = T) { 936 static if (isTemplateInstantiationOf!(T, Template)) { 937 alias instantiatonToTemplate = Template; 938 } else static if (isTemplate!T) { 939 alias instantiatonToTemplate = T; 940 } 941 } 942 943 private enum bool isTemplateInstantiationOf(T, alias Template) = is(T : Template!(Z), Z...); 944 private enum bool isTemplateInstantiationOf(alias T, alias Template) = is(typeof(T) : Template!(Z), Z...); 945 946 private template identifierEq(alias T, string identity) { 947 enum bool identifierEq = identifier!T == identity; 948 } 949 950 private template allUDAs(alias symbol) { 951 alias allUDAs = AliasSeq!(__traits(getAttributes, symbol)); 952 } 953 954 private template toValue(T) { 955 enum auto toValue = T(); 956 } 957 958 private template toValue(alias T) { 959 alias toValue = T; 960 } 961 962 private template isType(alias T) { 963 static if (__traits(compiles, () { T z = T.init; })) { 964 965 enum bool isType = true; 966 } else { 967 968 enum bool isType = false; 969 } 970 } 971 972 private template isClass(alias T) { 973 enum bool isClass = is(typeof(T) == class); 974 } 975 976 private template isClass(T) { 977 enum bool isClass = is(T == class); 978 } 979 980 private template isStruct(alias T) { 981 enum bool isStruct = is(typeof(T) == struct); 982 } 983 984 private template isStruct(T) { 985 enum bool isStruct = is(T == struct); 986 } 987 988 private template getPublicAggregateMembers(alias Symbol) { 989 alias getPublicAggregateMembers = Filter!( 990 templateAnd!( 991 partialSuffixed!( 992 partialPrefixed!( 993 isProtection, 994 Symbol 995 ), 996 "public" 997 ), 998 chain!( 999 hasMembers, 1000 partialPrefixed!( 1001 getMember, 1002 Symbol 1003 ) 1004 ) 1005 ), 1006 __traits(allMembers, Symbol) 1007 ); 1008 } 1009 1010 private template getPossibleComponents(alias Symbol) { 1011 alias getPossibleComponents = staticMap!( 1012 partialPrefixed!( 1013 getMember, 1014 Symbol 1015 ), 1016 Filter!( 1017 templateAnd!( 1018 partialSuffixed!( 1019 partialPrefixed!( 1020 isProtection, 1021 Symbol 1022 ), 1023 "public" 1024 ), 1025 chain!( 1026 isType, 1027 partialPrefixed!( 1028 getMember, 1029 Symbol 1030 ) 1031 ), 1032 chain!( 1033 templateOr!( 1034 isClass, 1035 isStruct 1036 ), 1037 partialPrefixed!( 1038 getMember, 1039 Symbol 1040 ) 1041 ) 1042 ), 1043 __traits(allMembers, Symbol) 1044 ) 1045 ); 1046 }