IoC.Configuration¶
IoC.Configuration is a container agnostic configuration of dependency injection.
IoC.Configuration is a wrapper around popular IoC containers, with additional functionality (see below). Currently Ninject and Autofac are supported through the usage of Nuget extension packages IoC.Configuration.Ninject and IoC.Configuration.Autofac.
- Among other things, it allows:
- Specifying dependency injection configuration in XML configuration file, as well as in IoC.Configuration module classes, or third party IoC container modules (e.g., Autofac or Ninject modules).
- Easy switching between containers to use for service resolution (e.g., Autofac, Ninject).
In addition, the configuration file has sections for settings, plugins, startup actions, dynamically generated implementations of interfaces (see Autogenerated Services), etc.
All these functionality will be explained in corresponding sections, however here is a quick overview:
The dependency injection bindings are done using any combination of the following techniques:
- In IoC.Configuration module classes using chained methods, pretty similar to how it is done in popular containers, Ninject and Autofac.
Note
The IoC.Configuration module classes should either implement IoC.Configuration.DiContainer.IDiModule, or extend the class IoC.Configuration.DiContainer.ModuleAbstr, and override the method Load().
In module classes of one of popular IoC packages (such as Autofac or Ninject). These modules will be referred as native modules.
In XML configuration file. This method is the preferred way to configure the dependency injection, since it is the most flexible. XML configuration files have sections for type bindings, as well as sections for IoC.Configuration or native (i.e., Autofac, Ninject, etc) modules.
Note
IoC.Configuration has its own syntax for type bindings, which reminds the syntax used in Ninject. However, IoC.Configuration translates these type bindings into 3-rd party IoC container (e.g., Autofac, Ninject, etc) bindings .
Type resolutions are done using one of popular IoC containers (e.g., Autofac, Ninject, etc), through the usage of implementations of IoC.Configuration.DiContainer.IDiManager interface.
Note
Currently, two implementations of IoC.Configuration.DiContainer.IDiManager are availabe, Ninject and Autofac implementations). These implementations are in packages IoC.Configuration.Ninject and IoC.Configuration.Autofac.
The container (e.g., Autofac, Ninject) used by IoC.Configuration can be switched in XML configuration file. Here is an exert from IoCConfiguration_Overview.xml, that shows the usage of element diManagers to specify container for resolving types:
<!--
The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager
-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
Sample Files¶
The XML configuration file schema is available at IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
- A template XML configuration file can be downloaded from IoC.Configuration.Template.xml.
Note
The template file and schema are also available in folder, where Nuget package IoC.Cnfiguration is unpacked.
- The XML configuration files listed below are used in some examples throughout the documentation. The file IoCConfiguration_Overview.xml provides an overview of various features of IoC.Configuration, while the other configuration files (e.g., IoCConfiguration_collection.xml, IoCConfiguration_constructedValue.xml), provide additional examples for some features.
Note
These configuration files can be found in test project IoC.Configuration.Tests. Most of type names in configuration files are meaningless (e.g., Interface1, Class1, etc)
XML Configuration File Schema¶
XML Configuration file is validated against the schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd below, when the file is loaded by IoC.Configuration.
This file can be found also in folder “IoC.Configuration.Content”, under the folder where Nuget package IoC.Configuration is downloaded (see the screenshot below), or can also be downloaded from IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or from oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.

To use Visual Studio code completion based on this schema, right click “Properties” on the XML configuration file, and select the schema in “Schemas” text box in properties tab (see the screenshot below).
Alternatively, reference the schema in xmlConfiguration element as displayed below:
1 2 3 4 5 | <iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--...-->
<iocConfiguration>
|
XML configuration file schema:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 | <?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="scopeValues">
<xs:restriction base="xs:string">
<!--The same object will be used for all service resolutions -->
<xs:enumeration value="singleton"/>
<!--New object will be created per request-->
<xs:enumeration value="transient"/>
<!--The same object will be created per scope lifetime., however different objects will be created in different lifetime scopes.-->
<xs:enumeration value="scopeLifetime"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="collectionTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="enumerable"/>
<xs:enumeration value="list"/>
<xs:enumeration value="readOnlyList"/>
<xs:enumeration value="array"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="DateTimeType">
<xs:restriction base="xs:string">
<xs:pattern
value="[0-9]{4}-(0[1-9]|1(0|1|2))-(0[1-9]|[1-2][0-9]|3[0-1]) ([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).([0-9]{3})"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="doubleType">
<xs:attribute name="value" use="required" type="xs:double"/>
</xs:complexType>
<xs:complexType name="namedDoubleType">
<xs:complexContent>
<xs:extension base="doubleType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="byteType">
<xs:attribute name="value" use="required" type="xs:byte"/>
</xs:complexType>
<xs:complexType name="namedByteType">
<xs:complexContent>
<xs:extension base="byteType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="int16Type">
<xs:attribute name="value" use="required" type="xs:short"/>
</xs:complexType>
<xs:complexType name="namedInt16Type">
<xs:complexContent>
<xs:extension base="int16Type">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="int32Type">
<xs:attribute name="value" use="required" type="xs:int"/>
</xs:complexType>
<xs:complexType name="namedInt32Type">
<xs:complexContent>
<xs:extension base="int32Type">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="int64Type">
<xs:attribute name="value" use="required" type="xs:long"/>
</xs:complexType>
<xs:complexType name="namedInt64Type">
<xs:complexContent>
<xs:extension base="int64Type">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="booleanType">
<xs:attribute name="value" use="required" type="xs:boolean"/>
</xs:complexType>
<xs:complexType name="namedBooleanType">
<xs:complexContent>
<xs:extension base="booleanType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="datetimeType">
<xs:attribute name="value" use="required" type="DateTimeType"/>
</xs:complexType>
<xs:complexType name="namedDatetimeType">
<xs:complexContent>
<xs:extension base="datetimeType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="stringType">
<xs:attribute name="value" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedStringType">
<xs:complexContent>
<xs:extension base="stringType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="settingValueType">
<xs:attribute name="settingName" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedSettingValueType">
<xs:complexContent>
<xs:extension base="settingValueType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="objectType">
<xs:attribute name="type" use="optional" type="xs:string"/>
<xs:attribute name="assembly" use="optional" type="xs:string"/>
<xs:attribute name="typeRef" use="optional" type="xs:string"/>
<xs:attribute name="value" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedObjectType">
<xs:complexContent>
<xs:extension base="objectType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="classMemberType">
<xs:sequence>
<xs:element name="parameters" type="namedValuesType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="class" use="optional" type="xs:string"/>
<xs:attribute name="assembly" use="optional" type="xs:string"/>
<xs:attribute name="classRef" use="optional" type="xs:string"/>
<xs:attribute name="memberName" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedClassMemberType">
<xs:complexContent>
<xs:extension base="classMemberType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="classMemberTypeWithDi">
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="class" use="optional" type="xs:string"/>
<xs:attribute name="assembly" use="optional" type="xs:string"/>
<xs:attribute name="classRef" use="optional" type="xs:string"/>
<xs:attribute name="memberName" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedClassMemberTypeWithDi">
<xs:complexContent>
<xs:extension base="classMemberTypeWithDi">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="injectedObjectType">
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="namedInjectedObjectType">
<xs:complexContent>
<xs:extension base="injectedObjectType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="parameterValueType">
<xs:attribute name="paramName" use="required" type="xs:string"/>
</xs:complexType>
<xs:complexType name="namedParameterValueType">
<xs:complexContent>
<xs:extension base="parameterValueType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="constructedValueType">
<xs:sequence>
<xs:element name="parameters" type="namedValuesType" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="namedConstructedValueType">
<xs:complexContent>
<xs:extension base="constructedValueType">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="constructedValueTypeWithDi">
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="namedConstructedValueTypeWithDi">
<xs:complexContent>
<xs:extension base="constructedValueTypeWithDi">
<xs:attribute name="name" use="required" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="collectionType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="byteType" minOccurs="1" maxOccurs="1"/>
<xs:element name="int16" type="int16Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int32" type="int32Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int64" type="int64Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="double" type="doubleType" minOccurs="1" maxOccurs="1"/>
<xs:element name="boolean" type="booleanType" minOccurs="1" maxOccurs="1"/>
<xs:element name="datetime" type="datetimeType" minOccurs="1" maxOccurs="1"/>
<xs:element name="string" type="stringType" minOccurs="1" maxOccurs="1"/>
<xs:element name="object" type="objectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="classMember" type="classMemberType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="constructedValueType" minOccurs="1" maxOccurs="1"/>
<xs:element name="collection" type="collectionType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="namedCollectionType">
<xs:complexContent>
<xs:extension base="collectionType">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="collectionType" type="collectionTypes" use="required"/>
<xs:attribute name="itemType" type="xs:string" use="optional"/>
<xs:attribute name="itemTypeRef" type="xs:string" use="optional"/>
<xs:attribute name="itemTypeAssembly" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="collectionTypeWithDi">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="byteType"/>
<xs:element name="int16" type="int16Type"/>
<xs:element name="int32" type="int32Type"/>
<xs:element name="int64" type="int64Type"/>
<xs:element name="double" type="doubleType"/>
<xs:element name="boolean" type="booleanType"/>
<xs:element name="datetime" type="datetimeType"/>
<xs:element name="string" type="stringType"/>
<xs:element name="object" type="objectType"/>
<xs:element name="classMember" type="classMemberTypeWithDi"/>
<xs:element name="settingValue" type="settingValueType"/>
<xs:element name="constructedValue" type="constructedValueTypeWithDi"/>
<xs:element name="injectedObject" type="injectedObjectType"/>
<xs:element name="collection" type="collectionTypeWithDi"/>
<xs:element name="parameterValue" type="parameterValueType"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="namedCollectionTypeWithDi">
<xs:complexContent>
<xs:extension base="collectionTypeWithDi">
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="collectionType" type="collectionTypes" use="required"/>
<xs:attribute name="itemType" type="xs:string" use="optional"/>
<xs:attribute name="itemTypeRef" type="xs:string" use="optional"/>
<xs:attribute name="itemTypeAssembly" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="defaultValuesType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="namedByteType" minOccurs="1" maxOccurs="1"/>
<xs:element name="int16" type="namedInt16Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int32" type="namedInt32Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int64" type="namedInt64Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="double" type="namedDoubleType" minOccurs="1" maxOccurs="1"/>
<xs:element name="boolean" type="namedBooleanType" minOccurs="1" maxOccurs="1"/>
<xs:element name="datetime" type="namedDatetimeType" minOccurs="1" maxOccurs="1"/>
<xs:element name="string" type="namedStringType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="namedConstructedValueType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="namedValuesType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="namedByteType" minOccurs="1" maxOccurs="1"/>
<xs:element name="int16" type="namedInt16Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int32" type="namedInt32Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int64" type="namedInt64Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="double" type="namedDoubleType" minOccurs="1" maxOccurs="1"/>
<xs:element name="boolean" type="namedBooleanType" minOccurs="1" maxOccurs="1"/>
<xs:element name="datetime" type="namedDatetimeType" minOccurs="1" maxOccurs="1"/>
<xs:element name="string" type="namedStringType" minOccurs="1" maxOccurs="1"/>
<xs:element name="object" type="namedObjectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="namedConstructedValueType" minOccurs="1" maxOccurs="1"/>
<xs:element name="collection" type="namedCollectionType" minOccurs="1" maxOccurs="1"/>
<xs:element name="classMember" type="namedClassMemberType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="settingValuesType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="namedByteType" minOccurs="1" maxOccurs="1"/>
<xs:element name="int16" type="namedInt16Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int32" type="namedInt32Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int64" type="namedInt64Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="double" type="namedDoubleType" minOccurs="1" maxOccurs="1"/>
<xs:element name="boolean" type="namedBooleanType" minOccurs="1" maxOccurs="1"/>
<xs:element name="datetime" type="namedDatetimeType" minOccurs="1" maxOccurs="1"/>
<xs:element name="string" type="namedStringType" minOccurs="1" maxOccurs="1"/>
<xs:element name="object" type="namedObjectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="namedConstructedValueType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="namedValuesTypeWithDi">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte" type="namedByteType" minOccurs="1" maxOccurs="1"/>
<xs:element name="int16" type="namedInt16Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int32" type="namedInt32Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="int64" type="namedInt64Type" minOccurs="1" maxOccurs="1"/>
<xs:element name="double" type="namedDoubleType" minOccurs="1" maxOccurs="1"/>
<xs:element name="boolean" type="namedBooleanType" minOccurs="1" maxOccurs="1"/>
<xs:element name="datetime" type="namedDatetimeType" minOccurs="1" maxOccurs="1"/>
<xs:element name="string" type="namedStringType" minOccurs="1" maxOccurs="1"/>
<xs:element name="object" type="namedObjectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="settingValue" type="namedSettingValueType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="namedConstructedValueTypeWithDi" minOccurs="1" maxOccurs="1"/>
<xs:element name="injectedObject" type="namedInjectedObjectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="collection" type="namedCollectionTypeWithDi" minOccurs="1" maxOccurs="1"/>
<xs:element name="classMember" type="namedClassMemberTypeWithDi" minOccurs="1" maxOccurs="1"/>
<xs:element name="parameterValue" type="namedParameterValueType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:element name="appDataDir">
<xs:complexType>
<xs:attribute name="path" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="plugins">
<xs:complexType>
<xs:sequence>
<xs:element name="plugin" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="enabled" type="xs:boolean" use="optional" default="true"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="pluginsDirPath" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="additionalAssemblyProbingPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="probingPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="path" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="assemblies">
<xs:complexType>
<xs:sequence>
<xs:element name="assembly" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="alias" type="xs:string" use="required"/>
<xs:attribute name="plugin" type="xs:string" use="optional"/>
<!--loadAlways is deprecated and will be deleted in the future.
All assemblies in configuration file are now added as references to dynamically generated assembly, however
.NET only loads assemblies that are used in referencing assembly-->
<xs:attribute name="loadAlways" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="overrideDirectory" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="typeDefinition">
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="genericTypeParameters">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element type="typeDefinition" name="typeDefinition"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
</xs:complexType>
<xs:complexType name="namedTypeDefinition">
<xs:complexContent>
<xs:extension base="typeDefinition">
<xs:attribute name="alias" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="typeDefinitions">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="typeDefinition" type="namedTypeDefinition"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!--<xs:element name="attributeValueTransformer">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="defaultValuesType" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="assembly" type="xs:string" use="optional" />
<xs:attribute name="typeRef" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="attributeValueTransformers">
<xs:complexType>
<xs:sequence>
<xs:element ref="attributeValueTransformer" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>-->
<xs:element name="parameterSerializer">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="defaultValuesType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="parameterSerializers">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="defaultValuesType" minOccurs="0" maxOccurs="1"/>
<xs:element name="serializers">
<xs:complexType>
<xs:sequence>
<xs:element ref="parameterSerializer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="serializerAggregatorType" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="serializerAggregatorTypeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="diManager">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="diManagers">
<xs:complexType>
<xs:sequence>
<xs:element ref="diManager" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="activeDiManagerName" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="settings" type="settingValuesType">
</xs:element>
<xs:element name="controllerAssembly">
<xs:complexType>
<xs:attribute name="assembly" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="controllerAssemblies">
<xs:complexType>
<xs:sequence>
<xs:element ref="controllerAssembly" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="webApi">
<xs:complexType>
<xs:sequence>
<xs:element ref="controllerAssemblies" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="settingsRequestor">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="modules">
<xs:complexType>
<xs:sequence>
<xs:element name="module" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
<xs:attribute name="enabled" type="xs:boolean" use="optional" default="true"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="implementation">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="scopeValues" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="serviceToProxy">
<xs:complexType>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="valueImplementation">
<xs:complexType>
<xs:choice>
<xs:element name="collection" type="collectionTypeWithDi"/>
<xs:element name="settingValue" type="settingValueType"/>
<xs:element name="object" type="objectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="classMember" type="classMemberTypeWithDi" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="constructedValueTypeWithDi" minOccurs="1" maxOccurs="1"/>
</xs:choice>
<xs:attribute name="scope" type="scopeValues" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="service">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:choice>
<xs:element ref="implementation"/>
<xs:element ref="valueImplementation"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
<xs:attribute name="registerIfNotRegistered" type="xs:boolean" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="proxyService">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element ref="serviceToProxy"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
<xs:attribute name="registerIfNotRegistered" type="xs:boolean" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="selfBoundService">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="scopeValues" use="required"/>
<xs:attribute name="registerIfNotRegistered" type="xs:boolean" default="false" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="services">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element ref="service" minOccurs="1" maxOccurs="1"/>
<xs:element ref="selfBoundService" minOccurs="1" maxOccurs="1"/>
<xs:element ref="proxyService" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="autoGeneratedMemberReturnValues">
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="constructedValue" type="constructedValueTypeWithDi"/>
<xs:element name="injectedObject" type="injectedObjectType"/>
<xs:element name="byte" type="byteType"/>
<xs:element name="int16" type="int16Type"/>
<xs:element name="int32" type="int32Type"/>
<xs:element name="int64" type="int64Type"/>
<xs:element name="double" type="doubleType"/>
<xs:element name="boolean" type="booleanType"/>
<xs:element name="datetime" type="datetimeType"/>
<xs:element name="string" type="stringType"/>
<xs:element name="object" type="objectType"/>
<xs:element name="settingValue" type="settingValueType"/>
<xs:element name="collection" type="collectionTypeWithDi"/>
<xs:element name="classMember" type="classMemberTypeWithDi"/>
<xs:element name="parameterValue" type="parameterValueType"/>
</xs:choice>
</xs:complexType>
<xs:element name="autoProperty">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="constructedValue" type="constructedValueTypeWithDi"/>
<xs:element name="injectedObject" type="injectedObjectType"/>
<xs:element name="byte" type="byteType"/>
<xs:element name="int16" type="int16Type"/>
<xs:element name="int32" type="int32Type"/>
<xs:element name="int64" type="int64Type"/>
<xs:element name="double" type="doubleType"/>
<xs:element name="boolean" type="booleanType"/>
<xs:element name="datetime" type="datetimeType"/>
<xs:element name="string" type="stringType"/>
<xs:element name="object" type="objectType"/>
<xs:element name="settingValue" type="settingValueType"/>
<xs:element name="collection" type="collectionTypeWithDi"/>
<xs:element name="classMember" type="classMemberTypeWithDi"/>
<xs:element name="parameterValue" type="parameterValueType"/>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="returnType" use="optional" type="xs:string"/>
<xs:attribute name="assembly" use="optional" type="xs:string"/>
<xs:attribute name="returnTypeRef" use="optional" type="xs:string"/>
<xs:attribute name="declaringInterface" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="methodSignature">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="byte">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="int16">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="int32">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="int64">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="double">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="boolean">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="datetime">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="string">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="object">
<xs:complexType>
<xs:attribute name="paramName" use="optional"></xs:attribute>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="autoMethod">
<xs:complexType>
<xs:sequence>
<xs:element ref="methodSignature" minOccurs="0" maxOccurs="1"/>
<xs:element name="if" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:complexContent>
<xs:extension base="autoGeneratedMemberReturnValues">
<xs:attribute name="parameter1" type="xs:string" use="optional"/>
<xs:attribute name="parameter2" type="xs:string" use="optional"/>
<xs:attribute name="parameter3" type="xs:string" use="optional"/>
<xs:attribute name="parameter4" type="xs:string" use="optional"/>
<xs:attribute name="parameter5" type="xs:string" use="optional"/>
<xs:attribute name="parameter6" type="xs:string" use="optional"/>
<xs:attribute name="parameter7" type="xs:string" use="optional"/>
<xs:attribute name="parameter8" type="xs:string" use="optional"/>
<xs:attribute name="parameter9" type="xs:string" use="optional"/>
<xs:attribute name="parameter10" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="default" type="autoGeneratedMemberReturnValues" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="returnType" use="optional" type="xs:string"/>
<xs:attribute name="assembly" use="optional" type="xs:string"/>
<xs:attribute name="returnTypeRef" use="optional" type="xs:string"/>
<xs:attribute name="reuseValue" type="xs:boolean" use="optional" default="false"/>
<xs:attribute name="declaringInterface" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="autoService">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element ref="autoMethod" minOccurs="1" maxOccurs="1"></xs:element>
<xs:element ref="autoProperty" minOccurs="1" maxOccurs="1"></xs:element>
</xs:choice>
</xs:sequence>
<xs:attribute name="interface" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="interfaceRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<!--<xs:complexType name="additionalAssemblyReferencesType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="assemblyRef">
<xs:complexType>
<xs:attribute name="alias" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>-->
<xs:complexType name="autoServiceCodeGeneratorType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:choice>
<xs:element name="object" type="objectType" minOccurs="1" maxOccurs="1"/>
<xs:element name="constructedValue" type="constructedValueType" minOccurs="1" maxOccurs="1"/>
<xs:element name="classMember" type="classMemberType" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:element name="autoServiceCustom">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="autoServiceCodeGenerator" type="autoServiceCodeGeneratorType" minOccurs="1"
maxOccurs="1"/>
<!--<xs:element name="additionalAssemblyReferences" type="additionalAssemblyReferencesType" minOccurs="0" maxOccurs="1" />-->
</xs:sequence>
<xs:attribute name="interface" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="interfaceRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="autoGeneratedServices">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element ref="autoService" minOccurs="1" maxOccurs="1"/>
<xs:element ref="autoServiceCustom" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="dependencyInjection">
<xs:complexType>
<xs:sequence>
<xs:element ref="modules" minOccurs="1" maxOccurs="1"/>
<xs:element ref="services" minOccurs="1" maxOccurs="1"/>
<xs:element ref="autoGeneratedServices" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="startupAction">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="startupActions">
<xs:complexType>
<xs:sequence>
<xs:element ref="startupAction" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="pluginImplementation">
<xs:complexType>
<xs:sequence>
<xs:element name="parameters" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
<xs:element name="injectedProperties" type="namedValuesTypeWithDi" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="optional"/>
<xs:attribute name="assembly" type="xs:string" use="optional"/>
<xs:attribute name="typeRef" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="pluginSetup">
<xs:complexType>
<xs:sequence>
<xs:element ref="pluginImplementation" minOccurs="1" maxOccurs="1"/>
<xs:element ref="typeDefinitions" minOccurs="0" maxOccurs="1"/>
<xs:element ref="settings" minOccurs="1" maxOccurs="1"/>
<xs:element ref="webApi" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dependencyInjection" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="plugin" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="pluginsSetup">
<xs:complexType>
<xs:sequence>
<xs:element ref="pluginSetup" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="iocConfiguration">
<xs:complexType>
<xs:sequence>
<xs:element ref="appDataDir" minOccurs="1" maxOccurs="1"/>
<xs:element ref="plugins" minOccurs="1" maxOccurs="1"/>
<xs:element ref="additionalAssemblyProbingPaths" minOccurs="1" maxOccurs="1"/>
<xs:element ref="assemblies" minOccurs="1" maxOccurs="1"/>
<xs:element ref="typeDefinitions" minOccurs="0" maxOccurs="1"/>
<!--<xs:element ref="attributeValueTransformers" minOccurs="0" maxOccurs="1" />-->
<xs:element ref="parameterSerializers" minOccurs="1" maxOccurs="1"/>
<xs:element ref="diManagers" minOccurs="1" maxOccurs="1"/>
<xs:element ref="settingsRequestor" minOccurs="0" maxOccurs="1"/>
<xs:element ref="settings" minOccurs="1" maxOccurs="1"/>
<xs:element ref="webApi" minOccurs="0" maxOccurs="1"/>
<xs:element ref="dependencyInjection" minOccurs="1" maxOccurs="1"/>
<xs:element ref="startupActions" minOccurs="1" maxOccurs="1"/>
<xs:element ref="pluginsSetup" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
|
XML Configuration Template¶
Here is a template XML configuration file that can be used to get started. This file can be found also in folder IoC.Configuration.Content, under the folder, where Nuget package IoC.Configuration is downloaded (see the screenshot below). This file can also be downloaded from IoC.Configuration.Template.xml

Template file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | <?xml version="1.0" encoding="utf-8"?>
<!--
Sample license text.
-->
<!--
This is a simple sample configuration file to use with IoC.Configuration library.
Some elements and attributes in this XML file should be modified per specific project.
For more complete example, look at files IoCConfiguration_Overview.xml and some ther configuration files in test project
IoC.Configuration.Tests at https://github.com/artakhak/IoC.Configuration/tree/master/IoC.Configuration.Tests.
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir. This is where dynamically generated DLLs are saved.-->
<appDataDir path="C:\Users\user1\AppData\Local\MyApplication" />
<plugins pluginsDirPath="c:\Program Files\MyApplication\DLLs\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--If Plugin1 is enabled, a folder c:\Program Files\MyApplication\DLLs\PluginDlls\Plugin1 should exist -->
<!--<plugin name="Plugin1" />-->
<!--<plugin name="Plugin2" enabled="false" />-->
</plugins>
<additionalAssemblyProbingPaths>
<probingPath path="c:\Program Files\MyApplication\DLLs\ThirdPartyLibs" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<assembly name="OROptimizer.Shared" alias="oroptimizer_shared" />
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
</assemblies>
<parameterSerializers serializerAggregatorType="OROptimizer.Serializer.TypeBasedSimpleSerializerAggregator">
<!--
Use parameters element to specify constructor parameters, if the type specified in 'serializerAggregatorType' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
<serializers>
</serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager">
<!--
Use parameters element to specify constructor parameters, if the type specified in 'type' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should specify a type that implements
SharedServices.ISettingsRequestor. The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency injection framework. In other words, constructor
parameters will be injected using bindings specified in dependencyInjection element.
-->
<!--<settingsRequestor type="MySettingsRequestor">
</settingsRequestor>-->
<settings>
<!--Example:
<int32 name="MySetting1" value="15"/>
-->
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_Overview.xml¶
The file IoCConfiguration_Overview.xml provides an overview of various features of IoC.Configuration
This configuration file can be downloaded downloaded from IoCConfiguration_Overview.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | <?xml version="1.0" encoding="utf-8"?>
<!--This is a demo IoC.Configuration file. Even though this configuration file, along with tests in folder SuccessfulConfigurationLoadTests
covers many use cases, some concepts are covered in more details in separate configuration files and tests.
Here is the list of other configuration files and tests that cover specific use cases:
Type reuse, generic types and arrays (elements typeDefinitions and typeDefinition and referencing types defined under typeDefinitions
element using attributes like typeRef, interfaceRef, classRef, etc): Look at configuration file
IoCConfiguration_GenericTypesAndTypeReUse.xml and tests in folder GenericTypesAndTypeReUse.
Element autoService: look at configuration file IoCConfiguration_autoService.xml and tests in folder AutoService.
Element autoServiceCustom: look at configuration file IoCConfiguration_autoServiceCustom.xml and tests in folder AutoService.
Element collection: look at configuration file IoCConfiguration_collection.xml and tests in folder Collection.
Element classMember and _classMember: prefix in "if" elements under autoMethod elements: look at configuration file
IoCConfiguration_classMember.xml and tests in folder ClassMember.
Element settingValue: look at configuration file IoCConfiguration_settingValue_ReferencingInConfiguration.xml and tests in folder SettingValue.
Element constructedValue: look at configuration file IoCConfiguration_constructedValue.xml and tests in folder ConstructedValue.
Element proxyService: look at configuration file IoCConfiguration_proxyService.xml and tests in folder ProxyService.
Element valueImplementation (to provide implementation as a value). Example is using a classMember, or settingValue elements to
provide an implementation for a service.: look at configuration file IoCConfiguration_valueImplementation.xml and tests in folder ValueImplementation.
-->
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\IoCConfiguration_Overview" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" />
<plugin name="Plugin3" enabled="false" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
<probingPath
path="TestFiles\TestAssemblyResolution" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<assembly name="OROptimizer.Shared" alias="oroptimizer_shared" />
<assembly name="IoC.Configuration" alias="ioc_config" />
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include
probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" overrideDirectory="TestFiles\DynamicallyLoadedDlls"/>
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.Plugin1WebApiControllers"
alias="plugin1api" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.ModulesForPlugin2"
alias="modules_plugin2" plugin="Plugin2"/>
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
<!--For more examples of type definitions and generic types, arrays, and re-using types defined under
typeDefinition element look at file IoCConfiguration_GenericTypesAndTypeReUse.xml, as well as tests
in folder GenericTypesAndTypeReUse.
-->
<typeDefinition alias="ReadOnlyListOf_IInterface1" type="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IInterface1]" />
<!--The type definition below is similar to C# type System.Collections.Generic.IEnumerable<SharedServices.Interfaces.IInterface1[]>-->
<typeDefinition alias="enumerableOfArray" type="System.Collections.Generic.IEnumerable[SharedServices.Interfaces.IInterface1#]" />
<!--The type definition below is similar to C# type System.Collections.Generic.IList<SharedServices.Interfaces.IInterface1[]>-->
<typeDefinition alias="listOfArray" type="System.Collections.Generic.IList" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Interfaces.IInterface1#" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="AutoService_IInterface1" type="IoC.Configuration.Tests.AutoService.Services.IInterface1" />
<typeDefinition alias="IActionValidator" type="SharedServices.Interfaces.IActionValidator" />
<typeDefinition alias="IProjectGuids" type="IoC.Configuration.Tests.AutoService.Services.IProjectGuids" />
<typeDefinition alias="ActionTypes" type="SharedServices.DataContracts.ActionTypes" />
<typeDefinition alias="Guid" type="System.Guid" />
<typeDefinition alias="ListOfInt" type="System.Collections.Generic.List[System.Int32]" >
</typeDefinition>
</typeDefinitions>
<!--assembly attribute is not required, and only is needed to make sure the type is looked at specific assembly
If the assembly attribute is omitted, the type will be looked in all assemblies specified in assemblies, plus some additional
assemblies such as OROptimizer.Shared, IoC.Configuration, etc.
-->
<parameterSerializers serializerAggregatorType="OROptimizer.Serializer.TypeBasedSimpleSerializerAggregator"
assembly="oroptimizer_shared">
<!--
Use parameters element to specify constructor parameters, if the type specified in 'serializerAggregatorType' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
<serializers>
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerDouble" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerLong" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerInt"/>
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerShort"/>
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerByte" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerBoolean" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerDateTime" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerString" />
<parameterSerializer type="TestPluginAssembly1.Implementations.DoorSerializer" />
<parameterSerializer type="TestPluginAssembly2.Implementations.WheelSerializer" />
<parameterSerializer type="TestPluginAssembly1.Implementations.UnsignedIntSerializerWithParameters" >
<parameters>
<int32 name="param1" value="25" />
<double name="param2" value="36.5" />
</parameters>
</parameterSerializer>
</serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settingsRequestor type="SharedServices.FakeSettingsRequestor">
</settingsRequestor>
<settings>
<int32 name="SynchronizerFrequencyInMilliseconds" value="5000" />
<double name="MaxCharge" value="155.7" />
<string name="DisplayValue" value="Some display value" />
<!--NOTE: For more comprehensive examples for constructedValue element,
look at file IoCConfiguration_constructedValue.xml and tests in folder ConstructedValue.-->
<constructedValue name="DefaultDBConnection" type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\SQLiteFiles\MySqliteDb.sqlite"/>
</parameters>
</constructedValue>
<object name="Project1Guid" typeRef="Guid" value="EA91B230-3FF8-43FA-978B-3261493D58A3" />
<object name="Project2Guid" typeRef="Guid" value="9EDC7F1A-6BD6-4277-9015-5A9277218681" />
<constructedValue name="Interface11_Value" type="SharedServices.Implementations.Interface11_Impl1">
<parameters>
<!-- Constructor parameter of SharedServices.Implementations.Interface11 is injected using a constructedValue element-->
<constructedValue name="param1" type="SharedServices.Implementations.Interface10_Impl1" >
<parameters>
<int32 name="param1" value="13" />
</parameters>
<injectedProperties>
<string name="Property2" value="Value 1"/>
</injectedProperties>
</constructedValue>
</parameters>
<injectedProperties>
<!-- Property SharedServices.Implementations.Interface11.Property2 is injected using a constructedValue element-->
<constructedValue name="Property2" type="SharedServices.Implementations.Interface10_Impl1" >
<parameters>
<int32 name="param1" value="17"/>
</parameters>
<injectedProperties>
<string name="Property2" value="Value 2"/>
</injectedProperties>
</constructedValue>
</injectedProperties>
</constructedValue>
<!--NOTE: For more comprehensive examples for collection element,
look at file IoCConfiguration_collection.xml and tests in folder Collection.-->
<constructedValue name="Collections" type="IoC.Configuration.Tests.Collection.Services.DemoCollectionInjection">
<parameters>
<!--Demo of injecting a collection into a constructor of DemoCollectionInjection in constructedValue element.-->
<collection name="intValues" collectionType="readOnlyList" itemType="System.Int32">
<int32 value="17"/>
<int32 value="14"/>
</collection>
</parameters>
<injectedProperties>
<!--Demo of injecting a collection into a property of DemoCollectionInjection in constructedValue element.-->
<collection name="Texts" collectionType="readOnlyList" itemType="System.String">
<string value="ABC, Inc"/>
<string value="Microsoft"/>
</collection>
</injectedProperties>
</constructedValue>
<boolean name="failCustomServiceValidation" value="false"/>
</settings>
<!--
webApi is an optional element that contains ASP.NET Core related
sections such as assemblies with API controllers, etc
-->
<webApi>
<controllerAssemblies>
<!--
Specify assemblies with API controllers.
The user of IoC.Configuration should add the assemblies to MVC using
IMvcBuilder.AddApplicationPart(System.Reflection.Assembly)
-->
<controllerAssembly assembly="dynamic1"></controllerAssembly>
</controllerAssemblies>
</webApi>
<dependencyInjection>
<modules>
<module type="IoC.Configuration.Tests.PrimitiveTypeDefaultBindingsModule" >
<parameters>
<!--Date time can be also long value for ticks. For example the datetime value below can
be replaced with 604096704000000000-->
<datetime name="defaultDateTime" value="1915-04-24 00:00:00.000" />
<double name="defaultDouble" value="0" />
<int16 name="defaultInt16" value="0" />
<classMember name="defaultInt32" class="System.Int32" memberName="MinValue"/>
</parameters>
</module>
<!--Type Modules.Autofac.AutofacModule1 is an Autofac module and is a
subclass of Autofac.AutofacModule-->
<module type="Modules.Autofac.AutofacModule1" >
<parameters>
<int32 name="param1" value="1" />
</parameters>
</module>
<!--Type Modules.IoC.DiModule1 is an IoC.Configuration module and is a subclass
of IoC.Configuration.DiContainer.ModuleAbstr-->
<module type="Modules.IoC.DiModule1" >
<parameters>
<int32 name="param1" value="2" />
</parameters>
</module>
<!--Type Modules.Ninject.NinjectModule1 is a Ninject module and is a
subclass of Ninject.Modules.NinjectModule-->
<module type="Modules.Ninject.NinjectModule1" >
<parameters>
<int32 name="param1" value="3" />
</parameters>
</module>
<module type="IoC.Configuration.Tests.AutoService.AutoServiceTestsModule" />
</modules>
<services>
<service type="DynamicallyLoadedAssembly1.Interfaces.IInterface1">
<implementation type="DynamicallyLoadedAssembly1.Implementations.Interface1_Impl1"
scope="singleton">
</implementation>
</service>
<service type="DynamicallyLoadedAssembly1.Interfaces.IInterface2">
<implementation type="DynamicallyLoadedAssembly1.Implementations.Interface2_Impl1"
scope="transient">
</implementation>
</service>
<service type="DynamicallyLoadedAssembly1.Interfaces.IInterface3">
<implementation type="DynamicallyLoadedAssembly1.Implementations.Interface3_Impl1"
scope="scopeLifetime">
</implementation>
</service>
<!--
Test DI picking the default constructor when instantiating the implementation, if parameters element is
present, and using non-default constructor otherwise, with injected parameters.
-->
<service type="SharedServices.Interfaces.IInterface9">
<implementation type="SharedServices.Implementations.Interface9_Impl1"
scope="singleton" />
</service>
<service type="SharedServices.Interfaces.IInterface8">
<implementation type="SharedServices.Implementations.Interface8_Impl1"
scope="singleton">
<!--
Since parameters is present, a default constructor will be used to construct an object, even though
Interface8_Impl1 has also a non default constructor.
-->
<parameters>
</parameters>
</implementation>
<implementation type="SharedServices.Implementations.Interface8_Impl2" scope="singleton">
<!--
Since parameters is not present, DI will pick a constructor with maximum number of parameters.
Note, Interface8_Impl2 has two constructors, a default one, and a constructor with parameters.
-->
</implementation>
</service>
<!--Injected constructor parameters with self bound services-->
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService1"
scope="singleton">
<parameters>
<int32 name="param1" value="14" />
<double name="param2" value="15.3" />
<injectedObject name="param3" type="DynamicallyLoadedAssembly1.Interfaces.IInterface1" />
</parameters>
</selfBoundService>
<!--Injected properties with self bound services-->
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService2"
scope="transient">
<injectedProperties>
<int32 name="Property1" value="17" />
<double name="Property2" value="18.1" />
<injectedObject name="Property3" type="DynamicallyLoadedAssembly1.Interfaces.IInterface1" />
</injectedProperties>
</selfBoundService>
<!--Life time scope with self bound services-->
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService3"
scope="scopeLifetime">
</selfBoundService>
<!--Test circular references between SharedServices.Interfaces.IInterface3 and SharedServices.Interfaces.IInterface4-->
<service type="SharedServices.Interfaces.IInterface3" >
<implementation type="SharedServices.Implementations.Interface3_Impl1"
scope="singleton">
<injectedProperties>
<injectedObject name="Property2" type="SharedServices.Interfaces.IInterface4" />
</injectedProperties>
</implementation>
</service>
<service type="SharedServices.Interfaces.IInterface4">
<implementation type="SharedServices.Implementations.Interface4_Impl1"
scope="singleton">
</implementation>
</service>
<!--Injected constructor parameters-->
<service type="SharedServices.Interfaces.IInterface2" >
<!--Test constructor parameters-->
<implementation type="SharedServices.Implementations.Interface2_Impl1"
scope="singleton">
<parameters>
<!--The value will be de-serialized using serializer TypeBasedSimpleSerializerDateTime
in parameterSerializers section.-->
<datetime name="param1" value="2014-10-29 23:59:59.099" />
<double name="param2" value="125.1" />
<injectedObject name="param3" type="SharedServices.Interfaces.IInterface3" />
</parameters>
</implementation>
<!--Test injected properties-->
<implementation type="SharedServices.Implementations.Interface2_Impl2"
scope="singleton">
<injectedProperties>
<!--The value of param2 will be de-serialized using serializer TypeBasedSimpleSerializerDateTime
in parameterSerializers section.-->
<datetime name="Property1" value="1915-04-24 00:00:00.001" />
<double name="Property2" value="365.41" />
<injectedObject name="Property3" type="SharedServices.Interfaces.IInterface3" />
</injectedProperties>
</implementation>
<!--Test constructor parameters with injected properties. Constructor values will be overridden by
injected properties.-->
<implementation type="SharedServices.Implementations.Interface2_Impl3"
scope="singleton">
<parameters>
<!--The value will be de-serialized using serializer TypeBasedSimpleSerializerDateTime in
parameterSerializers section.-->
<datetime name="param1" value="2017-10-29 23:59:59.099" />
<double name="param2" value="138.3" />
<!--
Inject specific implementation. Note, there is no binding for Interface3_Impl2.
IoC.Configuration** will automatically register a self bound service for a type specified in elements
injectedObject, if the type is not an abstract type or an interface, and if it is not already
registered in configuration file.
Also, using injectedObject, we can specify a type other than a type registered for interface
SharedServices.Implementations.Interface3 (i.e., the type of parameter param3).
In other words, no matter what bindings are specified for interface SharedServices.Implementations.Interface3,
the object injected for parameter param3 will be of type SharedServices.Implementations.Interface3_Impl2.
-->
<injectedObject name="param3" type="SharedServices.Implementations.Interface3_Impl2" />
</parameters>
<injectedProperties>
<double name="Property2" value="148.3" />
<!--
Inject specific implementation. Note, there is no binding for Interface3_Impl3.
IoC.Configuration** will automatically register a self bound service for a type specified in element
injectedObject, if the type is not an abstract type or an interface, and if it is not already
registered in configuration file.
Also, using injectedObject, we can specify a type other than a type registered for type of property
Property3 somewhere else. By using element injectedObject we explicitly state the type of the object
that should be injected, which is SharedServices.Implementations.Interface3_Impl3 in this example.
-->
<injectedObject name="Property3" type="SharedServices.Implementations.Interface3_Impl3" />
</injectedProperties>
</implementation>
<!--Test injected constructor parameters. Primitive type constructor parameters, such as DateTime and double,
will be injected with default values specified in module: IoC.Configuration.Tests.PrimitiveTypeDefaultBindingsModule.
-->
<implementation type="SharedServices.Implementations.Interface2_Impl4"
scope="singleton">
</implementation>
</service>
<!--Test constructed values to set implementation constructor parameter and property values-->
<service type="SharedServices.Interfaces.Airplane.IAirplane" >
<implementation type="SharedServices.Implementations.Airplane.Airplane" scope="singleton" >
<parameters>
<!--Tested constructed value in parameter-->
<constructedValue name="engine" type="SharedServices.Implementations.Airplane.AirplaneEngine">
<parameters>
<!--Constructed value parameters can also be constructed values. However, for simplicity, injected parameters were used -->
<injectedObject name="blade" type="SharedServices.Interfaces.Airplane.IAirplaneEngineBlade" />
<injectedObject name="rotor" type="SharedServices.Interfaces.Airplane.IAirplaneEngineRotor" />
</parameters>
<!--constructedValue element also can have injectedProperties child element to inject values into constructed object
properties which have public setters.-->
<!--<injectedProperties></injectedProperties>-->
</constructedValue>
</parameters>
</implementation>
<!--Tested constructed value to inject property values-->
<implementation type="SharedServices.Implementations.Airplane.Airplane" scope="singleton">
<injectedProperties>
<!--Injecting constructed value of type SharedServices.Implementations.Airplane.AirplaneEngine
into a property SharedServices.Implementations.Airplane.Airplane.Engine-->
<constructedValue name="Engine" type="SharedServices.Implementations.Airplane.AirplaneEngine">
<!--Class TestProjects.SharedServices.Implementations.Airplane.AirplaneEngine has a default constructor
which will be used in this case.-->
<!--After the object is created, the values of properties AirplaneEngine.Blade and AirplaneEngine.Rotor will
be injected using injectedProperties element.-->
<injectedProperties>
<!--Constructed value parameters can also be constructed values. However, for simplicity, injected parameters were used -->
<injectedObject name="Blade" type="SharedServices.Interfaces.Airplane.IAirplaneEngineBlade" />
<injectedObject name="Rotor" type="SharedServices.Interfaces.Airplane.IAirplaneEngineRotor" />
</injectedProperties>
</constructedValue>
</injectedProperties>
</implementation>
</service>
<service type="SharedServices.Interfaces.Airplane.IAirplaneEngineBlade">
<implementation type="SharedServices.Implementations.Airplane.AirplaneEngineBlade" scope="singleton"></implementation>
</service>
<service type="SharedServices.Interfaces.Airplane.IAirplaneEngineRotor">
<implementation type="SharedServices.Implementations.Airplane.AirplaneEngineRotor" scope="singleton"></implementation>
</service>
<!--<selfBoundService type="SharedServices.Implementations.ActionValidator3" scope="transient">
<parameters>
<int32 name="intParam" value="5" />
</parameters>
</selfBoundService>-->
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.CleanupJob2"
scope="transient">
<parameters>
<injectedObject name="cleanupJobData"
type="DynamicallyLoadedAssembly1.Implementations.CleanupJobData2" />
</parameters>
</selfBoundService>
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.CleanupJob3"
scope="singleton">
<injectedProperties>
<injectedObject name="CleanupJobData"
type="DynamicallyLoadedAssembly1.Implementations.CleanupJobData2"/>
</injectedProperties>
</selfBoundService>
<service type="SharedServices.Interfaces.ICleanupJobData">
<implementation type="DynamicallyLoadedAssembly1.Implementations.CleanupJobData"
scope="singleton">
</implementation>
</service>
<!--Service implemented by plugins-->
<service type="SharedServices.Interfaces.IInterface5">
<implementation type="SharedServices.Implementations.Interface5_Impl1"
scope="singleton" />
<implementation type="TestPluginAssembly1.Implementations.Interface5_Plugin1Impl"
scope="singleton" />
<implementation type="TestPluginAssembly2.Implementations.Interface5_Plugin2Impl"
scope="transient" />
<implementation type="TestPluginAssembly3.Implementations.Interface5_Plugin3Impl"
scope="transient" />
</service>
<!--
Test registerIfNotRegistered. Note, SharedServices.Interfaces.IInterface6 is already registered in
module Modules.IoC.DiModule1 for implementation SharedServices.Implementations.Interface6_Impl1.
Therefore, implementation SharedServices.Implementations.Interface6_Impl2 will not be registered.
-->
<service type="SharedServices.Interfaces.IInterface6"
registerIfNotRegistered="true">
<implementation type="SharedServices.Implementations.Interface6_Impl2"
scope="singleton" />
</service>
<!--
Note, service SharedServices.Interfaces.IInterface7 was not registered before. Therefore its implementations
registered below will be registered.
-->
<service type="SharedServices.Interfaces.IInterface7"
registerIfNotRegistered="true">
<implementation type="SharedServices.Implementations.Interface7_Impl1"
scope="singleton" />
</service>
<selfBoundService type="SharedServices.Implementations.SelfBoundService1"
registerIfNotRegistered="true" scope="singleton">
</selfBoundService>
<service type="SharedServices.Interfaces.IInterface12">
<implementation type="SharedServices.Implementations.Interface12_Impl1" scope="singleton">
<parameters>
<!--Setting with name Interface11_Value is injected into constructor parameter param1 of
class SharedServices.Implementations.Interface12_Impl1-->
<!--NOTE: For more comprehensive examples for settingValue element,
look at file IoCConfiguration_settingValue_ReferencingInConfiguration.xml and tests in folder SettingValue.-->
<settingValue name="param1" settingName="Interface11_Value"/>
</parameters>
<injectedProperties>
<!--Setting with name Interface11_Value is injected into property
SharedServices.Implementations.Interface12_Impl1.Property2-->
<settingValue name="Property2" settingName="Interface11_Value"/>
</injectedProperties>
</implementation>
</service>
<service type="SharedServices.Interfaces.IDbConnection">
<valueImplementation scope="singleton">
<settingValue settingName="DefaultDBConnection"/>
</valueImplementation>
</service>
<!--NOTE: For more comprehensive examples for collection element,
look at file IoCConfiguration_collection.xml and tests in folder Collection.-->
<!--NOTE: For more comprehensive examples for valueImplementation element,
look at file IoCConfiguration_valueImplementation.xml and tests in folder ValueImplementation.-->
<service type="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IDbConnection]">
<valueImplementation scope="singleton">
<collection>
<settingValue settingName="DefaultDBConnection"/>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2012"/>
<string name="databaseName" value="DB1"/>
<string name="userName" value="user1"/>
<string name="password" value="password123"/>
</parameters>
</constructedValue>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2016"/>
<string name="databaseName" value="DB1"/>
<string name="userName" value="user1"/>
<string name="password" value="password123"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
<!--NOTE: For more comprehensive examples for proxyService element,
look at file IoCConfiguration_proxyService.xml and tests in folder ProxyService.-->
<!--
Using proxyService we can configure binding of a parent interface IActionValidatorFactoryBase in such a way, that it is resolved
using the same binding set up for extending interface IActionValidatorFactory.
For example auto-generated service IActionValidatorFactory implements methods and properties in both IActionValidatorFactory
as well as in parent interface IActionValidatorFactoryBase. By using proxyService we can inject the auto-generated implementation
for IActionValidatorFactory into classes which depend on its parent interface IActionValidatorFactoryBase.
-->
<proxyService type="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactoryBase">
<serviceToProxy type="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"/>
</proxyService>
<!--START-Test binding an interface to the ame instance to which a self-bound class is bound-->
<selfBoundService type="SharedServices.Implementations.Interface13_Impl1" scope="singleton" />
<!--NOTE: Using proxyService allows us to bind
SharedServices.Interfaces.IInterface13 to the same instance of SharedServices.Implementations.Interface13_Impl1 to which
SharedServices.Implementations.Interface13_Impl1 was bound using selfBoundService element.
If we used "implementation" element under service and specified a type SharedServices.Implementations.Interface13_Impl1
instead of using "proxyService", then SharedServices.Interfaces.IInterface13 would have been
bound to a different instance of SharedServices.Implementations.Interface13_Impl1. In other words resolving
SharedServices.Implementations.Interface13_Impl1 and SharedServices.Interfaces.IInterface13 would have resulted in
different instances of SharedServices.Implementations.Interface13_Impl1.
Using "proxyService" element might be useful when we have module(s) that scan assemblies and self-binds
non-abstract classes. In this cases we can use "proxyService" element if we want the interface
specified in "proxyService" element to resolve to exactly the same value to which the self bound class is bound.
-->
<proxyService type="SharedServices.Interfaces.IInterface13">
<serviceToProxy type="SharedServices.Implementations.Interface13_Impl1"/>
</proxyService>
<service type="SharedServices.Interfaces.IInterface14">
<implementation type="SharedServices.Implementations.Interface14_Impl1" scope="singleton" />
</service>
<!--END-Test binding an interface to the ame instance to which a self-bound class is bound-->
<!--Note, ActionValidatorsUser constructor has a parameter of type
IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactoryBase.
Since there is a proxyService element mapping the service IActionValidatorFactoryBase to IActionValidatorFactory,
an instance of auto-generated service IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory will be injected.
-->
<selfBoundService type="IoC.Configuration.Tests.ProxyService.Services.ActionValidatorsUser" scope="singleton">
</selfBoundService>
<!--System.Collections.Generic.List<System.Int32> will be bound to a list of three integers: 19, 2, 17-->
<service typeRef="ListOfInt">
<valueImplementation scope="singleton">
<collection>
<int32 value="19"/>
<int32 value="2"/>
<int32 value="17"/>
</collection>
</valueImplementation>
</service>
<!--Resolving System.Collections.Generic.IEnumerable<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IEnumerable[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--Resolving System.Collections.Generic.IReadOnlyList<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IReadOnlyList[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--Resolving System.Collections.Generic.IList<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IList[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--
Demo of classMember element to use static or non-static variables, properties and result of a call to parameterless
method to generate value used in configuration file.
NOTE: For more comprehensive examples for classMember element and "_classMember:" prefix in attributes in "if" elements in
autoService element, look at file IoCConfiguration_classMember.xml and tests in folder ClassMember.
-->
<service type="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.ClassMember.Services.IAppInfo]">
<valueImplementation scope="singleton">
<collection>
<constructedValue type="IoC.Configuration.Tests.ClassMember.Services.AppInfo">
<parameters>
<!--We inject the constant value IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId1
into constructor of AppInfo for parameter appId.
We can also use non constant static variables, as well as static properties and parameterless methods.
-->
<classMember name="appId"
class="IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds"
memberName="AppId1"/>
</parameters>
</constructedValue>
<constructedValue type="IoC.Configuration.Tests.ClassMember.Services.AppInfo">
<injectedProperties>
<!--Since SharedServices.Implementations.SelfBoundService1.IntValue is a non-static property,
an instance of SharedServices.Implementations.SelfBoundService1 will be resolved from the DI container,
and the value of IntValue of resolved instance will be injected into property AppInfo.AppId.
Note, we can also use parameterless methods.
Also, if the class in class attribute is non-interface, non-abstract, and has a public constructor,
IoC.Configuration will generated a binding for that class, if one is not specified in configuration file
or IoC.Configuration modules.
-->
<classMember name="AppId" class="SharedServices.Implementations.SelfBoundService1"
memberName="IntValue"/>
</injectedProperties>
</constructedValue>
<constructedValue type="IoC.Configuration.Tests.ClassMember.Services.AppInfo">
<parameters>
<!--The enum value IoC.Configuration.Tests.ClassMember.Services.AppTypes.App1 is injected into constructor of
AppInfo for parameter appId-->
<classMember name="appId"
class="IoC.Configuration.Tests.ClassMember.Services.AppTypes"
memberName="App1"/>
</parameters>
</constructedValue>
<!--
An example of calling a non static factory method to create an instance of IAppInfo.
Since method IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory.CreateAppInfo(appId, appDescription)
is non-static, an instance of IAppInfoFactory will be resolved using the DI container.
Also, since IAppInfoFactory is an interface, a binding for IAppInfoFactory should be configured in configuration
file or in some module.
-->
<classMember class="IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory" memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1258"/>
<string name="appDescription" value="App info created with non-static method call."/>
</parameters>
</classMember>
<!--
An example of calling a static factory method to create an instance of IAppInfo.
-->
<classMember class="IoC.Configuration.Tests.ClassMember.Services.StaticAppInfoFactory" memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1259"/>
<string name="appDescription" value="App info created with static method call."/>
</parameters>
</classMember>
</collection>
</valueImplementation>
</service>
<service type="IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory">
<implementation type="IoC.Configuration.Tests.ClassMember.Services.AppInfoFactory" scope="singleton"/>
</service>
</services>
<autoGeneratedServices>
<!--NOTE: For more comprehensive examples for autoService element, look at
file IoCConfiguration_autoService.xml and tests in folder AautoService.-->
<!--The scope for autoService implementations is always singleton -->
<autoService interfaceRef="IProjectGuids" >
<!--Note, since property Project1 in IoC.Configuration.Tests.AutoService.Services.IProjectGuids has
a setter, the implementation will implement the setter as well.-->
<autoProperty name="Project1" returnTypeRef="Guid">
<object typeRef="Guid" value="966FE6A6-76AC-4895-84B2-47E27E58FD02"/>
</autoProperty>
<autoProperty name="Project2" returnTypeRef="Guid">
<object typeRef="Guid" value="AC4EE351-CE69-4F89-A362-F833489FD9A1"/>
</autoProperty>
<autoMethod name="GetDefaultProject" returnTypeRef="Guid">
<!--No methodSignature is required, since the method does not have any parameters.-->
<default>
<!--TODO: change the returned value to classMember which references IProjectGuids.Project1 -->
<object typeRef="Guid" value="1E08071B-D02C-4830-AE3C-C9E78A29EA37"/>
</default>
</autoMethod>
<!---IoC.Configuration.Tests.AutoService.Services.IProjectGuids also has a method NotImplementedMethod()
which will be auto-implemented as well.-->
</autoService>
<!--Demo of referencing auto-implemented method parameters using parameterValue element-->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IAppInfoFactory">
<autoMethod name="CreateAppInfo" returnType="IoC.Configuration.Tests.AutoService.Services.IAppInfo">
<methodSignature>
<int32 paramName="appId"/>
<string paramName="appDescription"/>
</methodSignature>
<default>
<constructedValue type="IoC.Configuration.Tests.AutoService.Services.AppInfo">
<parameters>
<!--The value of name attribute is the name of constructor parameter in AppInfo-->
<!--
The value of paramName attribute is the name of parameter in IAppInfoFactory.CreateAppInfo.
This parameter should be present under autoMethod/methodSignature element.
-->
<!--In this example the values of name and paramName are similar, however they don't
have to be.-->
<parameterValue name="appId" paramName="appId" />
<parameterValue name="appDescription" paramName="appDescription" />
</parameters>
</constructedValue>
</default>
</autoMethod>
</autoService>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
<autoProperty name="DefaultActionValidator" returnType="SharedServices.Interfaces.IActionValidator">
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorDefault"/>
</autoProperty>
<autoProperty name="PublicProjectId" returnType="System.Guid" >
<object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/>
</autoProperty>
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"
reuseValue="true">
<methodSignature>
<!--paramName attribute is optional, however it makes the auto-implementation more readable. -->
<object paramName="actionType" typeRef="ActionTypes"/>
<object paramName="projectGuid" type="System.Guid"/>
</methodSignature>
<!--Parameter actionType (parameter1) value: In this example we use class member ViewFilesList (enum value) in enumeration
SharedServices.DataContracts.ActionTypes. Note, we use alias ActionTypes to reference the enum type declared in typeDefinitions section.
-->
<!--Parameter projectGuid (parameter2) value: The string "F79C3F23-C63F-4EB0-A513-7A8772A82B35" will be de-serialized to a System.Guid value,
using the default OROptimizer.Serializer.TypeBasedSimpleSerializerGuid serializer. More serializers can be provided in section
parameterSerializers-->
<if parameter1="_classMember:ActionTypes.ViewFilesList" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
<collection>
<constructedValue type="SharedServices.Implementations.ActionValidator3">
<parameters>
<int32 name="intParam" value="7"/>
</parameters>
</constructedValue>
<!--Constructor of ActionValidatorWithDependencyOnActionValidatorFactory has a parameter of type
IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory. Therefore an instance of auto-generated service IActionValidatorFactory
will be injected.
-->
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorWithDependencyOnActionValidatorFactory"/>
<constructedValue type=" IoC.Configuration.Tests.AutoService.Services.ActionValidator1" >
<parameters>
<injectedObject name="param1" typeRef="AutoService_IInterface1" />
</parameters>
<injectedProperties>
<!-- Note, we could have used constructedValue element to inject a constructed value into property
ActionValidator1.Property2. However, to keep the example simple, injectedObject was used -->
<injectedObject name="Property2" type="IoC.Configuration.Tests.AutoService.Services.IInterface2" />
</injectedProperties>
</constructedValue>
<injectedObject type="TestPluginAssembly1.Implementations.Plugin1ActionValidator"/>
<classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers" memberName="ActionValidator1" />
<!--Since DefaultActionValidator property in IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider interface is
not static, IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider will be injected.
Therefore, a binding should be setup for this class (or the interface should be auto-implemented
using autoService element)
-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="DefaultActionValidator"/>
<!--Since Plugin3 is disabled, Plugin3ActionValidator will be ignored -->
<injectedObject type="TestPluginAssembly3.Implementations.Plugin3ActionValidator"/>
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this example we use full class path for
SharedServices.DataContracts.ActionTypes in parameter1, instead of referencing a type declared in typeDefinitions element.
-->
<!--Parameter projectGuid (parameter2) value: In this case we reference the Project1Guid setting value in settings section, instead
of using a Guid string-->
<if parameter1="_classMember:ActionTypes.ViewFileContents" parameter2="_settings:Project1Guid">
<collection>
<!--Since IoC.Configuration.Tests.AutoService.Services.ActionValidator1 and SharedServices.Implementations.ActionValidator2 are
concrete (non-interface and non-abstract) classes), and have public constructors,
self bound service bindings for these classes will be automatically added, if binding for these classes are not specified
in configuration file or in some module of type IoC.Configuration.DiContainer.IDiModule -->
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator1" />
<!--Since GetViewOnlyActionvalidator() method in IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider
interface is not static, IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider will be injected.
Therefore, a binding should be setup for this class (or the interface should be auto-implemented using
autoService element).
-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="GetViewOnlyActionvalidator"/>
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this case we use constant value DefaultActionType declared in
class IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.
-->
<!--Parameter projectGuid (parameter2) value: In this case we use the value of property Project1 in
IoC.Configuration.Tests.AutoService.Services.IProjectGuids. Since the property Project1 is not static,
class IoC.Configuration.Tests.AutoService.Services.IProjectGuids will be injected.
-->
<if parameter1="_classMember:IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.DefaultActionType"
parameter2="_classMember:IProjectGuids.Project1">
<collection>
<!--Lets assume no validators are needed for this case-->
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this case we use enum value
SharedServices.DataContracts.ActionTypes.ViewFileContents. We use a shortcut (an alias) ActionTypes to reference a
reference the class SharedServices.DataContracts.ActionTypes declared in typeDefintions section.
-->
<!--Parameter projectGuid (parameter2) value: In this case we use the value returned by a call to static method
GetDefaultProjectGuid() in class IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.
-->
<if parameter1="_classMember:ActionTypes.ViewFileContents"
parameter2="_classMember:IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.GetDefaultProjectGuid">
<!--Continue here.-->
<collection>
<!--Since IoC.Configuration.Tests.AutoService.Services.ActionValidator1 and SharedServices.Implementations.ActionValidator2 are
concrete (non-interface and non-abstract classes), and have public constructors,
self bound service bindings for these classes will be automatically added, if binding for these classes
are not specified in configuration file or in some module of type IoC.Configuration.DiContainer.IDiModule -->
<injectedObject type="SharedServices.Implementations.ActionValidator2" />
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator1" />
</collection>
</if>
<!--Note parameter2 references PublicProjectId property in this
auto-generated IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory service. -->
<if parameter1="_classMember:ActionTypes.ViewFilesList"
parameter2="_classMember:IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory.PublicProjectId">
<collection>
<!--Note, we can reference a property in this auto-generated
IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory service.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/>
</collection>
</if>
<!--if none of conditions above are true, the default value will be returned by interface implementation.-->
<default>
<collection>
<!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<injectedObject type="DynamicallyLoadedAssembly2.ActionValidator4"/>
</collection>
</default>
</autoMethod>
<!--Overloaded method GetValidators uses parameters of types System.Int2 and System.string, instead of
SharedServices.DataContracts.ActionTypes and System.Guid, as in case above.-->
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]">
<methodSignature>
<!--paramName attribute is optional, however it makes the auto-implementation more readable. -->
<int32 paramName="actionTypeId"/>
<string paramName="projectGuid" />
</methodSignature>
<!-- Attributes parameter1 and parameter2 map values of parameters param1 and param2 in GetInstances() method to returned values. -->
<if parameter1="0" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
<collection>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator4" />
</collection>
</if>
<default>
<collection>
<!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"
memberName="DefaultActionValidator"/>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers"
memberName="GetDefaultActionValidator" />
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="AdminLevelActionValidator"/>
</collection>
</default>
</autoMethod>
<!--Note, interface IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory also has a method
void SomeMethodThatWillNotBeImplemented(int param1, string param2) and a property int SomeUnImplementedProperty { get; },'
we chose not to implement in configuration file. Unimplemented methods and properties will be auto-implemented to return default values,
based on return type defaults.
-->
</autoService>
<!--IMemberAmbiguityDemo demonstrates cases when there are multiple occurrences
of auto-generated methods and properties with same signatures and return types
in IMemberAmbiguityDemo and its base interfaces.
-->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo">
<!--GetIntValues(): IReadOnlyList<int> GetIntValues(int param1, string param2)-->
<autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" >
<methodSignature>
<int32 paramName="param1"/>
<string paramName="param2"/>
</methodSignature>
<if parameter1="1" parameter2="str1">
<collection>
<int32 value="17"/>
</collection>
</if>
<default>
<collection>
<int32 value="18"/>
<int32 value="19"/>
</collection>
</default>
</autoMethod>
<!--
This method is declared in IMemberAmbiguityDemo_Parent3, which is a base interface for IMemberAmbiguityDemo.
We can provide implementation for this interface, even though it has a similar signature and return type as the method
method IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo.GetIntValues.
By using the attribute 'declaringInterface', we make a distinction between these two.
-->
<autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent3">
<methodSignature>
<int32 paramName="param1"/>
<string paramName="param2"/>
</methodSignature>
<default>
<collection>
<int32 value="3"/>
</collection>
</default>
</autoMethod>
<!---
The method GetDbConnection(System.Guid appGuid) that return IDbConnection is in two base interfaces
of IMemberAmbiguityDemo: in IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1 and in
IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2.
Therefore, to avoid ambiguity, we have to specify the declaring interface in attribute 'declaringInterface'.
We can specify an implementation for IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2.GetDbConnection(),
and IoC.Configuration will generate a similar auto-implementation for the similar method in IMemberAmbiguityDemo_Parent1
as well.
-->
<autoMethod name="GetDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2">
<methodSignature>
<object paramName="appGuid" type="System.Guid"/>
</methodSignature>
<default>
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\mySqliteDatabase.sqlite"/>
</parameters>
</constructedValue>
</default>
</autoMethod>
<!--
Both IMemberAmbiguityDemo_Parent1 and IMemberAmbiguityDemo_Parent2 have properties called DefaultDbConnection
with the same return types. We can auto-implement this property for each of these interfaces by using
declaringInterface attribute in autoProperty element to explicitly specify the interface that own
the property (declaringInterface can be used in autoMethod as well as demonstrated above)
-->
<!--Auto-implementation of IMemberAmbiguityDemo_Parent1.DefaultDbConnection-->
<autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1">
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\IMemberAmbiguityDemo_Parent1_Db.sqlite"/>
</parameters>
</constructedValue>
</autoProperty>
<!--Auto-implementation of IMemberAmbiguityDemo_Parent2.DefaultDbConnection-->
<autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2">
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\IMemberAmbiguityDemo_Parent2_Db.sqlite"/>
</parameters>
</constructedValue>
</autoProperty>
<!--
Method GetNumericValue() occurs in both IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2
and IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1_Parent. However, since the return types
are different (System.Double in IMemberAmbiguityDemo_Parent2, and System.Int32 in IMemberAmbiguityDemo_Parent1_Parent),
we can auto-implement both them, without using attribute 'declaringInterface' to separate these two implementation.
-->
<!--IMemberAmbiguityDemo_Parent2.GetNumericValue() with return type of System.Double-->
<autoMethod name="GetNumericValue" returnType="System.Double" >
<default>
<double value="17.3"/>
</default>
</autoMethod>
<!--IMemberAmbiguityDemo_Parent1_Parent.GetNumericValue() with return type of System.Int32-->
<autoMethod name="GetNumericValue" returnType="System.Int32" >
<default>
<int32 value="19"/>
</default>
</autoMethod>
<!--
Property NumericValue occurs in both IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1
and IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2. However, since the return types
are different (System.Double in IMemberAmbiguityDemo_Parent1, and System.Int32 in IMemberAmbiguityDemo_Parent2),
we can auto-implement both them, without using attribute 'declaringInterface' to separate these two implementation.
-->
<!--IMemberAmbiguityDemo_Parent1.NumericValue with return type of System.Double-->
<autoProperty name="NumericValue" returnType="System.Double" >
<double value="18.2"/>
</autoProperty>
<!--IMemberAmbiguityDemo_Parent2.NumericValue with return type of System.Int32-->
<autoProperty name="NumericValue" returnType="System.Int32" >
<int32 value="14"/>
</autoProperty>
<!---Auto-implementing Method with optional parameters:
int MethodWithOptionalParameters(int param1, double param2 = 3.5, int param3=7); -->
<autoMethod name="MethodWithOptionalParameters" returnType="System.Int32">
<methodSignature>
<int32 paramName="param1"/>
<double paramName="param2"/>
<int32 paramName="param3"/>
</methodSignature>
<if parameter1="3" parameter2="3.5" parameter3="7">
<int32 value="17"/>
</if>
<default>
<int32 value="18"/>
</default>
</autoMethod>
</autoService>
<!--Interface specified in autoServiceCustom is auto-implemented by implementation of
IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator
that is specified in autoServiceCodeGenerator element.-->
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IAuthorsRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="15" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IBooksRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="25" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IAuthorBooksRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="35" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
<startupAction type="DynamicallyLoadedAssembly1.Implementations.StartupAction1">
<!--Use parameters element to specify constructor parameters if necessary.-->
<!--<parameters></parameters>-->
<!--Use injectedProperties element to inject properties into startup action if necessary.-->
<!--<injectedProperties></injectedProperties>-->
</startupAction>
<startupAction type="DynamicallyLoadedAssembly1.Implementations.StartupAction2">
</startupAction>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1">
<parameters>
<int64 name="param1" value="25" />
</parameters>
<injectedProperties>
<int64 name="Property2" value="35"/>
</injectedProperties>
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="25" />
<int64 name="Int64Setting1" value="38" />
<string name="StringSetting1" value="String Value 1" />
</settings>
<webApi>
<controllerAssemblies>
<!--
Specify assemblies with API controllers.
The user of IoC.Configuration should add the assemblies to MVC using
IMvcBuilder.AddApplicationPart(System.Reflection.Assembly)
-->
<controllerAssembly assembly="pluginassm1" />
<controllerAssembly assembly="plugin1api" />
</controllerAssemblies>
</webApi>
<dependencyInjection>
<modules>
<module type="ModulesForPlugin1.Ninject.NinjectModule1">
<parameters>
<int32 name="param1" value="101" />
</parameters>
</module>
<module type="ModulesForPlugin1.Autofac.AutofacModule1" >
<parameters>
<int32 name="param1" value="102" />
</parameters>
</module>
<module type="ModulesForPlugin1.IoC.DiModule1" >
<parameters>
<int32 name="param1" value="103" />
</parameters>
</module>
</modules>
<services>
<service type="TestPluginAssembly1.Interfaces.IDoor">
<implementation type="TestPluginAssembly1.Implementations.Door"
scope="transient">
<parameters>
<int32 name="Color" value="3" />
<double name="Height" value="180" />
</parameters>
</implementation>
</service>
<service type="TestPluginAssembly1.Interfaces.IRoom">
<implementation type="TestPluginAssembly1.Implementations.Room"
scope="transient">
<parameters>
<object name="door1" type="TestPluginAssembly1.Interfaces.IDoor"
value="5,185.1" />
<injectedObject name="door2" type="TestPluginAssembly1.Interfaces.IDoor" />
</parameters>
<injectedProperties>
<object name="Door2" type="TestPluginAssembly1.Interfaces.IDoor"
value="7,187.3" />
</injectedProperties>
</implementation>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory">
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IEnumerable[TestPluginAssembly1.Interfaces.IResourceAccessValidator]"
reuseValue="true" >
<methodSignature>
<string paramName="resourceName"/>
</methodSignature>
<if parameter1="public_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</if>
<if parameter1="admin_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
</collection>
</if>
<default>
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2">
<parameters>
<boolean name="param1" value="true" />
<double name="param2" value="25.3" />
<string name="param3" value="String value" />
</parameters>
<injectedProperties>
<double name="Property2" value="5.3" />
</injectedProperties>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="TestPluginAssembly2.Interfaces.IWheel">
<implementation type="TestPluginAssembly2.Implementations.Wheel"
scope="transient">
<parameters>
<int32 name="Color" value="5" />
<double name="Height" value="48" />
</parameters>
</implementation>
</service>
<service type="TestPluginAssembly2.Interfaces.ICar">
<implementation type="TestPluginAssembly2.Implementations.Car"
scope="transient">
<parameters>
<object name="wheel1" type="TestPluginAssembly2.Interfaces.IWheel" value="248,40" />
</parameters>
<injectedProperties>
<object name="Wheel1" type="TestPluginAssembly2.Interfaces.IWheel" value="27,45" />
<injectedObject name="Wheel2" type="TestPluginAssembly2.Interfaces.IWheel"/>
</injectedProperties>
</implementation>
</service>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3">
</pluginImplementation>
<settings></settings>
<webApi>
<controllerAssemblies>
<!--
Specify assemblies with API controllers.
The user of IoC.Configuration should add the assemblies to MVC using
IMvcBuilder.AddApplicationPart(System.Reflection.Assembly)
-->
<controllerAssembly assembly="pluginassm3" />
</controllerAssemblies>
</webApi>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_GenericTypesAndTypeReUse.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_GenericTypesAndTypeReUse.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | <?xml version="1.0" encoding="utf-8"?>
<!--This configuration demonstrates usage of types. Types can be specified in various elements either by using 'type' attribute, and an
optional 'assembly' attribute, or by using typeRef (or some other variations, such as interfaceRef), to reference a type defined in section
'typeDefinitions'.
In other words, every typeRef attribute can be replaced with 'type' (along with optional 'assembly' attribute)-->
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_TypeTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="OROptimizer.Shared" alias="oroptimizer_shared" />
<assembly name="IoC.Configuration" alias="ioc_config" />
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
<assembly name="System.Private.CoreLib" alias="corlib"/>
</assemblies>
<typeDefinitions>
<typeDefinition alias="ReadOnlyListOf_IInterface1" type="System.Collections.Generic.IReadOnlyList">
<genericTypeParameters>
<typeDefinition type="SharedServices.Interfaces.IInterface1" assembly="shared_services" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="IEnumerableOf_IInterface1"
type="System.Collections.Generic.IEnumerable[SharedServices.Interfaces.IInterface1]" />
<typeDefinition alias="IGeneric1_1_of_Interface1_Impl1"
type="SharedServices.Interfaces.Generic.IGeneric1_1[SharedServices.Implementations.Interface1_Impl1]">
</typeDefinition>
<!--The type definition below is similar to C# type SharedServices.Interfaces.IInterface1[]-->
<typeDefinition alias="arrayOfInterface1" type="SharedServices.Interfaces.IInterface1#" />
<!--The type definition below is similar to C# type System.Collections.Generic.IEnumerable<SharedServices.Interfaces.IInterface1[]>-->
<typeDefinition alias="enumerableOfArray" type="System.Collections.Generic.IEnumerable[SharedServices.Interfaces.IInterface1#]" />
<!--The type definition below is similar to C# type System.Collections.Generic.IList<SharedServices.Interfaces.IInterface1[]>-->
<typeDefinition alias="listOfArray" type="System.Collections.Generic.IList" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Interfaces.IInterface1#" />
</genericTypeParameters>
</typeDefinition>
<!--The type definition below is similar to C# type
SharedServices.Interfaces.Generic.IGeneric4_2<SharedServices.Interfaces.IInterface1[], SharedServices.Interfaces.IInterface2[]>[]-->
<typeDefinition alias="arraysOfGenericTypes" type="SharedServices.Interfaces.Generic.IGeneric4_2[SharedServices.Interfaces.IInterface1#, SharedServices.Interfaces.IInterface2#]#" />
<typeDefinition alias="Generic1_1_of_Interface1_Impl1" type="SharedServices.Implementations.Generic.Generic1_1[SharedServices.Implementations.Interface1_Impl1]">
</typeDefinition>
<typeDefinition alias="Generic4_2_a" type="SharedServices.Implementations.Generic.Generic4_2" >
<genericTypeParameters>
<typeDefinition type="System.Int32" />
<typeDefinition type="System.String" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="Generic4_2_b" type="SharedServices.Implementations.Generic.Generic4_2" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Implementations.Generic.Generic2_1[SharedServices.Implementations.Interface1_Impl1]" />
<typeDefinition type="SharedServices.Implementations.Generic.Generic2_1">
<genericTypeParameters>
<typeDefinition type="System.Int64" />
</genericTypeParameters>
</typeDefinition>
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="Generic4_2_c" type="SharedServices.Implementations.Generic.Generic4_2" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Interfaces.Generic.IGeneric2_1">
<genericTypeParameters>
<typeDefinition type="System.String" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition type="SharedServices.Interfaces.Generic.IGeneric2_1[SharedServices.Implementations.Interface1_Impl2]" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="Generic4_2_d" type="SharedServices.Implementations.Generic.Generic4_2" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Interfaces.Generic.IGeneric2_1">
<genericTypeParameters>
<typeDefinition type="System.String" />
</genericTypeParameters>
</typeDefinition>
<typeDefinition type="SharedServices.Interfaces.Generic.IGeneric2_1">
<genericTypeParameters>
<typeDefinition type="System.Double" />
</genericTypeParameters>
</typeDefinition>
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="Interface1" type="SharedServices.Interfaces.IInterface1"></typeDefinition>
<typeDefinition alias="Interface1_Impl1" type="SharedServices.Implementations.Interface1_Impl1"></typeDefinition>
<typeDefinition alias="module2" type="Modules.IoC.DiModule2" />
<typeDefinition alias="SerializerAggregator" type="OROptimizer.Serializer.TypeBasedSimpleSerializerAggregator" />
<typeDefinition alias="TestTypeRefTestClass3Serializer" type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.GenericTypesAndTypeReUseTests.TestTypeRefTestClass3Serializer" />
<typeDefinition alias="TestTypeRefTestClass1" type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.GenericTypesAndTypeReUseTests.TestTypeRefTestClass1" />
<typeDefinition alias="TestTypeRefTestClass2" type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.GenericTypesAndTypeReUseTests.TestTypeRefTestClass2" />
<typeDefinition alias="TestTypeRefTestClass3" type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.GenericTypesAndTypeReUseTests.TestTypeRefTestClass3" />
<!--Plugin types can be used in non plugin definitions. However, usage of this types in other non-plugin sections should confirm'
to certain restictions.-->
<typeDefinition alias="pluginTypeDef" type="TestPluginAssembly1.Implementations.Window" assembly="pluginassm1"></typeDefinition>
</typeDefinitions>
<parameterSerializers serializerAggregatorTypeRef="SerializerAggregator">
<!--
Use parameters element to specify constructor parameters, if the type specified in 'serializerAggregatorType' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
<serializers>
<parameterSerializer typeRef="TestTypeRefTestClass3Serializer" />
</serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settingsRequestor type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.SettingsRequestor"
assembly="tests">
<!-- TODO:-->
</settingsRequestor>
<settings>
<constructedValue name="GenericSetting1" typeRef="Generic1_1_of_Interface1_Impl1" >
<parameters>
<constructedValue name="param1" typeRef="Interface1_Impl1">
</constructedValue>
</parameters>
</constructedValue>
</settings>
<dependencyInjection>
<modules>
<module typeRef="module2">
<parameters>
<constructedValue name="param1" typeRef="Interface1_Impl1" />
</parameters>
</module>
</modules>
<services>
<selfBoundService typeRef="Interface1_Impl1" scope="singleton" />
<service typeRef="Interface1">
<implementation typeRef="Interface1_Impl1" scope="singleton"></implementation>
</service>
<service typeRef="IGeneric1_1_of_Interface1_Impl1">
<valueImplementation scope="singleton">
<settingValue settingName="GenericSetting1"/>
</valueImplementation>
<implementation typeRef="Generic1_1_of_Interface1_Impl1" scope="singleton"></implementation>
<implementation type="SharedServices.Implementations.Generic.Generic1_1[SharedServices.Implementations.Interface1_Impl1]" scope="singleton" />
</service>
<service type="SharedServices.Interfaces.Generic.IGeneric2_1[SharedServices.Implementations.Generic.Generic3_1[System.Int32]]" >
<implementation type="SharedServices.Implementations.Generic.Generic2_1[SharedServices.Implementations.Generic.Generic3_1[System.Int32]]"
scope="singleton">
<parameters>
<constructedValue name="param1" type="SharedServices.Implementations.Generic.Generic3_1[System.Int32]">
<parameters>
<int32 name="param1" value="17"/>
</parameters>
</constructedValue>
</parameters>
</implementation>
</service>
<selfBoundService typeRef="Generic4_2_b" scope="singleton">
<parameters>
<constructedValue name="param1" type="SharedServices.Implementations.Generic.Generic2_1[SharedServices.Implementations.Interface1_Impl1]">
<parameters>
<injectedObject name="param1" type="SharedServices.Implementations.Interface1_Impl1" />
</parameters>
</constructedValue>
</parameters>
<injectedProperties>
<constructedValue name="Value2" type="SharedServices.Implementations.Generic.Generic2_1[System.Int64]">
<parameters>
<int64 name="param1" value="19"/>
</parameters>
</constructedValue>
</injectedProperties>
</selfBoundService>
<selfBoundService typeRef="TestTypeRefTestClass2" scope="singleton">
</selfBoundService>
<selfBoundService typeRef="TestTypeRefTestClass1" scope="singleton">
<parameters>
<injectedObject name="param1" typeRef="TestTypeRefTestClass2" />
<object name="param2" typeRef="TestTypeRefTestClass3" value="5"/>
</parameters>
<injectedProperties>
<injectedObject name="Property3" typeRef="TestTypeRefTestClass2" />
<object name="Property4" typeRef="TestTypeRefTestClass3" value="7"/>
</injectedProperties>
</selfBoundService>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
<startupAction type="IoC.Configuration.Tests.GenericTypesAndTypeReUse.StartupAction1"
assembly="tests">
<!-- TODO:-->
<!--Use parameters element to specify constructor parameters if necessary.-->
<!--<parameters></parameters>-->
<!--Use injectedProperties element to inject properties into startup action if necessary.-->
<!--<injectedProperties></injectedProperties>-->
</startupAction>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<typeDefinitions>
<!--Generic1_1_of_Interface1_Impl1 type definition overrides the definition in non-plugins section.-->
<typeDefinition alias="Generic1_1_of_Interface1_Impl1" type="SharedServices.Implementations.Generic.Generic1_1[TestPluginAssembly1.Implementations.Interface1_Impl1]">
</typeDefinition>
<typeDefinition alias="ReadOnlyListOfGenericType" type="System.Collections.Generic.IReadOnlyList" assembly="corlib">
<genericTypeParameters>
<typeDefinition type="SharedServices.Implementations.Generic.Generic3_1" >
<genericTypeParameters>
<typeDefinition type="SharedServices.Implementations.Interface1_Impl1" />
</genericTypeParameters>
</typeDefinition>
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="IDoor" type="TestPluginAssembly1.Interfaces.IDoor"></typeDefinition>
<typeDefinition alias="Door" type="TestPluginAssembly1.Implementations.Door"></typeDefinition>
<typeDefinition alias="plugin1Module" type="ModulesForPlugin1.IoC.DiModule2"></typeDefinition>
</typeDefinitions>
<settings>
<constructedValue name="PluginGenericSetting1" typeRef="Generic1_1_of_Interface1_Impl1" >
<parameters>
<constructedValue name="param1" type="TestPluginAssembly1.Implementations.Interface1_Impl1">
</constructedValue>
</parameters>
</constructedValue>
</settings>
<dependencyInjection>
<modules>
<module typeRef="plugin1Module">
<parameters>
<constructedValue name="param1" typeRef="Door">
<parameters>
<int32 name="color" value="255"/>
<int32 name="height" value="200"/>
</parameters>
</constructedValue>
</parameters>
</module>
</modules>
<services>
<selfBoundService typeRef="Door" scope="singleton">
<parameters>
<int32 name="color" value="258"/>
<int32 name="height" value="100" />
</parameters>
</selfBoundService>
<service typeRef="IDoor">
<implementation typeRef="Door" scope="singleton">
<parameters>
<int32 name="color" value="255"/>
<int32 name="height" value="25"/>
</parameters>
</implementation>
</service>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2_TypeTests" assembly="pluginassm2">
<!--<parameters>
</parameters>-->
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_autoService.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_autoService.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_AutoServiceTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" enabled="true" />
<plugin name="Plugin3" enabled="false" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
<typeDefinition alias="AutoService_IInterface1" type="IoC.Configuration.Tests.AutoService.Services.IInterface1" />
<typeDefinition alias="IActionValidator" type="SharedServices.Interfaces.IActionValidator" />
<typeDefinition alias="IProjectGuids" type="IoC.Configuration.Tests.AutoService.Services.IProjectGuids" />
<typeDefinition alias="ActionTypes" type="SharedServices.DataContracts.ActionTypes" />
<typeDefinition alias="Guid" type="System.Guid" />
</typeDefinitions>
<parameterSerializers>
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<constructedValue name="DefaultDBConnection" type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\SQLiteFiles\MySqliteDb.sqlite"/>
</parameters>
</constructedValue>
<object name="Project1Guid" typeRef="Guid" value="EA91B230-3FF8-43FA-978B-3261493D58A3" />
<object name="Project2Guid" typeRef="Guid" value="9EDC7F1A-6BD6-4277-9015-5A9277218681" />
</settings>
<dependencyInjection>
<modules>
<module type="IoC.Configuration.Tests.PrimitiveTypeDefaultBindingsModule">
<parameters>
<!--Date time can be also long value for ticks. For example the datetime value below can
be replaced with 604096704000000000-->
<datetime name="defaultDateTime" value="1915-04-24 00:00:00.000" />
<double name="defaultDouble" value="0" />
<int16 name="defaultInt16" value="0" />
<classMember name="defaultInt32" class="System.Int32" memberName="MinValue"/>
</parameters>
</module>
<module type="IoC.Configuration.Tests.AutoService.AutoServiceTestsModule" />
</modules>
<services>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interfaceRef="IProjectGuids" >
<!--Note, since property Project1 in IoC.Configuration.Tests.AutoService.Services.IProjectGuids has
a setter, the implementation will implement the setter as well.-->
<autoProperty name="Project1" returnTypeRef="Guid">
<object typeRef="Guid" value="966FE6A6-76AC-4895-84B2-47E27E58FD02"/>
</autoProperty>
<autoProperty name="Project2" returnTypeRef="Guid">
<object typeRef="Guid" value="AC4EE351-CE69-4F89-A362-F833489FD9A1"/>
</autoProperty>
<autoMethod name="GetDefaultProject" returnTypeRef="Guid">
<!--No methodSignature is required, since the method does not have any parameters.-->
<default>
<!--TODO: change the returned value to classMember which references IProjectGuids.Project1 -->
<object typeRef="Guid" value="1E08071B-D02C-4830-AE3C-C9E78A29EA37"/>
</default>
</autoMethod>
<!---IoC.Configuration.Tests.AutoService.Services.IProjectGuids also has a method NotImplementedMethod()
which will be auto-implemented as well.-->
</autoService>
<!--Demo of referencing auto-implemented method parameters using parameterValue element-->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IAppInfoFactory">
<autoMethod name="CreateAppInfo" returnType="IoC.Configuration.Tests.AutoService.Services.IAppInfo">
<methodSignature>
<int32 paramName="appId"/>
<string paramName="appDescription"/>
</methodSignature>
<default>
<constructedValue type="IoC.Configuration.Tests.AutoService.Services.AppInfo">
<parameters>
<!--The value of name attribute is the name of constructor parameter in AppInfo-->
<!--
The value of paramName attribute is the name of parameter in IAppInfoFactory.CreateAppInfo.
This parameter should be present under autoMethod/methodSignature element.
-->
<!--In this example the values of name and paramName are similar, however they don't
have to be.-->
<parameterValue name="appId" paramName="appId" />
<parameterValue name="appDescription" paramName="appDescription" />
</parameters>
</constructedValue>
</default>
</autoMethod>
</autoService>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
<autoProperty name="DefaultActionValidator" returnType="SharedServices.Interfaces.IActionValidator">
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorDefault"/>
</autoProperty>
<autoProperty name="PublicProjectId" returnType="System.Guid" >
<object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/>
</autoProperty>
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"
reuseValue="true">
<methodSignature>
<!--paramName attribute is optional, however it makes the auto-implementation more readable. -->
<object paramName="actionType" typeRef="ActionTypes"/>
<object paramName="projectGuid" type="System.Guid"/>
</methodSignature>
<!--Parameter actionType (parameter1) value: In this example we use class member ViewFilesList (enum value) in enumeration
SharedServices.DataContracts.ActionTypes. Note, we use alias ActionTypes to reference the enum type declared in typeDefinitions section.
-->
<!--Parameter projectGuid (parameter2) value: The string "F79C3F23-C63F-4EB0-A513-7A8772A82B35" will be de-serialized to a System.Guid value,
using the default OROptimizer.Serializer.TypeBasedSimpleSerializerGuid serializer. More serializers can be provided in section
parameterSerializers-->
<if parameter1="_classMember:ActionTypes.ViewFilesList" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
<collection>
<constructedValue type="SharedServices.Implementations.ActionValidator3">
<parameters>
<int32 name="intParam" value="7"/>
</parameters>
</constructedValue>
<!--Constructor of ActionValidatorWithDependencyOnActionValidatorFactory has a parameter of type
IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory. Therefore an instance of auto-generated service IActionValidatorFactory
will be injected.
-->
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorWithDependencyOnActionValidatorFactory"/>
<constructedValue type=" IoC.Configuration.Tests.AutoService.Services.ActionValidator1" >
<parameters>
<injectedObject name="param1" typeRef="AutoService_IInterface1" />
</parameters>
<injectedProperties>
<!-- Note, we could have used constructedValue element to inject a constructed value into property
ActionValidator1.Property2. However, to keep the example simple, injectedObject was used -->
<injectedObject name="Property2" type="IoC.Configuration.Tests.AutoService.Services.IInterface2" />
</injectedProperties>
</constructedValue>
<injectedObject type="TestPluginAssembly1.Implementations.Plugin1ActionValidator"/>
<classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers" memberName="ActionValidator1" />
<!--Since DefaultActionValidator property in IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider interface is
not static, IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider will be injected.
Therefore, a binding should be setup for this class (or the interface should be auto-implemented
using autoService element)
-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="DefaultActionValidator"/>
<!--Since Plugin3 is disabled, Plugin3ActionValidator will be ignored -->
<injectedObject type="TestPluginAssembly3.Implementations.Plugin3ActionValidator"/>
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this example we use full class path for
SharedServices.DataContracts.ActionTypes in parameter1, instead of referencing a type declared in typeDefinitions element.
-->
<!--Parameter projectGuid (parameter2) value: In this case we reference the Project1Guid setting value in settings section, instead
of using a Guid string-->
<if parameter1="_classMember:ActionTypes.ViewFileContents" parameter2="_settings:Project1Guid">
<collection>
<!--Since IoC.Configuration.Tests.AutoService.Services.ActionValidator1 and SharedServices.Implementations.ActionValidator2 are
concrete (non-interface and non-abstract) classes), and have public constructors,
self bound service bindings for these classes will be automatically added, if binding for these classes are not specified
in configuration file or in some module of type IoC.Configuration.DiContainer.IDiModule -->
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator1" />
<!--Since GetViewOnlyActionvalidator() method in IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider
interface is not static, IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider will be injected.
Therefore, a binding should be setup for this class (or the interface should be auto-implemented using
autoService element).
-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="GetViewOnlyActionvalidator"/>
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this case we use constant value DefaultActionType declared in
class IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.
-->
<!--Parameter projectGuid (parameter2) value: In this case we use the value of property Project1 in
IoC.Configuration.Tests.AutoService.Services.IProjectGuids. Since the property Project1 is not static,
class IoC.Configuration.Tests.AutoService.Services.IProjectGuids will be injected.
-->
<if parameter1="_classMember:IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.DefaultActionType"
parameter2="_classMember:IProjectGuids.Project1">
<collection>
<!--Lets assume no validators are needed for this case-->
</collection>
</if>
<!--Parameter actionType (parameter1) value: In this case we use enum value
SharedServices.DataContracts.ActionTypes.ViewFileContents. We use a shortcut (an alias) ActionTypes to reference a
reference the class SharedServices.DataContracts.ActionTypes declared in typeDefintions section.
-->
<!--Parameter projectGuid (parameter2) value: In this case we use the value returned by a call to static method
GetDefaultProjectGuid() in class IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.
-->
<if parameter1="_classMember:ActionTypes.ViewFileContents"
parameter2="_classMember:IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers.GetDefaultProjectGuid">
<!--Continue here.-->
<collection>
<!--Since IoC.Configuration.Tests.AutoService.Services.ActionValidator1 and SharedServices.Implementations.ActionValidator2 are
concrete (non-interface and non-abstract classes), and have public constructors,
self bound service bindings for these classes will be automatically added, if binding for these classes
are not specified in configuration file or in some module of type IoC.Configuration.DiContainer.IDiModule -->
<injectedObject type="SharedServices.Implementations.ActionValidator2" />
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator1" />
</collection>
</if>
<!--Note parameter2 references PublicProjectId property in this
auto-generated IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory service. -->
<if parameter1="_classMember:ActionTypes.ViewFilesList"
parameter2="_classMember:IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory.PublicProjectId">
<collection>
<!--Note, we can reference a property in this auto-generated
IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory service.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/>
</collection>
</if>
<!--if none of conditions above are true, the default value will be returned by interface implementation.-->
<default>
<collection>
<!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<injectedObject type="DynamicallyLoadedAssembly2.ActionValidator4"/>
</collection>
</default>
</autoMethod>
<!--Overloaded method GetValidators uses parameters of types System.Int32 and System.string, instead of
SharedServices.DataContracts.ActionTypes and System.Guid, as in case above.-->
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]">
<methodSignature>
<!--paramName attribute is optional, however it makes the auto-implementation more readable. -->
<int32 paramName="actionTypeId"/>
<string paramName="projectGuid" />
</methodSignature>
<!-- Attributes parameter1 and parameter2 map values of parameters param1 and param2 in GetInstances() method to returned values. -->
<if parameter1="0" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
<collection>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator4" />
</collection>
</if>
<default>
<collection>
<!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.-->
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"
memberName="DefaultActionValidator"/>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers"
memberName="GetDefaultActionValidator" />
<classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
memberName="AdminLevelActionValidator"/>
</collection>
</default>
</autoMethod>
<!--Note, interface IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory also has a method
void SomeMethodThatWillNotBeImplemented(int param1, string param2) and a property int SomeUnImplementedProperty { get; },'
we chose not to implement in configuration file. Unimplemented methods and properties will be auto-implemented to return default values,
based on return type defaults.
-->
</autoService>
<!--IMemberAmbiguityDemo demonstrates cases when there are multiple occurrences
of auto-generated methods and properties with same signatures and return types
in IMemberAmbiguityDemo and its base interfaces.
-->
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo">
<!--GetIntValues(): IReadOnlyList<int> GetIntValues(int param1, string param2)-->
<autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" >
<methodSignature>
<int32 paramName="param1"/>
<string paramName="param2"/>
</methodSignature>
<if parameter1="1" parameter2="str1">
<collection>
<int32 value="17"/>
</collection>
</if>
<default>
<collection>
<int32 value="18"/>
<int32 value="19"/>
</collection>
</default>
</autoMethod>
<!--
This method is declared in IMemberAmbiguityDemo_Parent3, which is a base interface for IMemberAmbiguityDemo.
We can provide implementation for this interface, even though it has a similar signature and return type as the method
IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo.GetIntValues.
By using the attribute 'declaringInterface', we make a distinction between these two.
-->
<autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent3">
<methodSignature>
<int32 paramName="param1"/>
<string paramName="param2"/>
</methodSignature>
<default>
<collection>
<int32 value="3"/>
</collection>
</default>
</autoMethod>
<!---
The method GetDbConnection(System.Guid appGuid) that return IDbConnection is in two base interfaces
of IMemberAmbiguityDemo: in IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1 and in
IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2.
Therefore, to avoid ambiguity, we have to specify the declaring interface in attribute 'declaringInterface'.
We can specify an implementation for IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2.GetDbConnection(),
and IoC.Configuration will generate a similar auto-implementation for the similar method in IMemberAmbiguityDemo_Parent1
as well.
-->
<autoMethod name="GetDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2">
<methodSignature>
<object paramName="appGuid" type="System.Guid"/>
</methodSignature>
<default>
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\mySqliteDatabase.sqlite"/>
</parameters>
</constructedValue>
</default>
</autoMethod>
<!--
Both IMemberAmbiguityDemo_Parent1 and IMemberAmbiguityDemo_Parent2 have properties called DefaultDbConnection
with the same return types. We can auto-implement this property for each of these interfaces by using
declaringInterface attribute in autoProperty element to explicitly specify the interface that own
the property (declaringInterface can be used in autoMethod as well as demonstrated above)
-->
<!--Auto-implementation of IMemberAmbiguityDemo_Parent1.DefaultDbConnection-->
<autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1">
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\IMemberAmbiguityDemo_Parent1_Db.sqlite"/>
</parameters>
</constructedValue>
</autoProperty>
<!--Auto-implementation of IMemberAmbiguityDemo_Parent2.DefaultDbConnection-->
<autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection"
declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2">
<constructedValue type="SharedServices.Implementations.SqliteDbConnection">
<parameters>
<string name="filePath" value="c:\IMemberAmbiguityDemo_Parent2_Db.sqlite"/>
</parameters>
</constructedValue>
</autoProperty>
<!--
Method GetNumericValue() occurs in both IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2
and IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1_Parent. However, since the return types
are different (System.Double in IMemberAmbiguityDemo_Parent2, and System.Int32 in IMemberAmbiguityDemo_Parent1_Parent),
we can auto-implement both them, without using attribute 'declaringInterface' to separate these two implementation.
-->
<!--IMemberAmbiguityDemo_Parent2.GetNumericValue() with return type of System.Double-->
<autoMethod name="GetNumericValue" returnType="System.Double" >
<default>
<double value="17.3"/>
</default>
</autoMethod>
<!--IMemberAmbiguityDemo_Parent1_Parent.GetNumericValue() with return type of System.Int32-->
<autoMethod name="GetNumericValue" returnType="System.Int32" >
<default>
<int32 value="19"/>
</default>
</autoMethod>
<!--
Property NumericValue occurs in both IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1
and IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2. However, since the return types
are different (System.Double in IMemberAmbiguityDemo_Parent1, and System.Int32 in IMemberAmbiguityDemo_Parent2),
we can auto-implement both them, without using attribute 'declaringInterface' to separate these two implementation.
-->
<!--IMemberAmbiguityDemo_Parent1.NumericValue with return type of System.Double-->
<autoProperty name="NumericValue" returnType="System.Double" >
<double value="18.2"/>
</autoProperty>
<!--IMemberAmbiguityDemo_Parent2.NumericValue with return type of System.Int32-->
<autoProperty name="NumericValue" returnType="System.Int32" >
<int32 value="14"/>
</autoProperty>
<!---Auto-implementing Method with optional parameters:
int MethodWithOptionalParameters(int param1, double param2 = 3.5, int param3=7); -->
<autoMethod name="MethodWithOptionalParameters" returnType="System.Int32">
<methodSignature>
<int32 paramName="param1"/>
<double paramName="param2"/>
<int32 paramName="param3"/>
</methodSignature>
<if parameter1="3" parameter2="3.5" parameter3="7">
<int32 value="17"/>
</if>
<default>
<int32 value="18"/>
</default>
</autoMethod>
</autoService>
<autoService interface="IoC.Configuration.Tests.AutoService.Services.INullableTypesTestInterface">
<autoMethod name="GetNullableInt" returnType="System.Nullable[System.Int32]">
<default>
<int32 value="17"/>
</default>
</autoMethod>
<autoMethod name="GetNullablesList" returnType="System.Collections.Generic.IReadOnlyList[System.Nullable[System.Int32]]">
<default>
<collection>
<int32 value="12" />
<int32 value="18" />
</collection>
</default>
</autoMethod>
<autoMethod name="MethodWithNullableParameter" returnType="System.Int32">
<methodSignature>
<object paramName="value" type="System.Nullable[System.Double]"/>
</methodSignature>
<default>
<int32 value="23"/>
</default>
</autoMethod>
<autoMethod name="MethodWithParameterAsListOfNullableValues" returnType="System.Int32">
<methodSignature>
<object paramName="value" type="System.Collections.Generic.IReadOnlyList[System.Nullable[System.Double]]"/>
</methodSignature>
<default>
<int32 value="19"/>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
<autoService interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory">
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IEnumerable[TestPluginAssembly1.Interfaces.IResourceAccessValidator]"
reuseValue="true" >
<methodSignature>
<string paramName="resourceName"/>
</methodSignature>
<if parameter1="public_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</if>
<if parameter1="admin_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
</collection>
</if>
<default>
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true" />
<double name="param2" value="25.3" />
<string name="param3" value="String value" />
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_autoServiceCustom.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_autoServiceCustom.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_AutoServiceCustomTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1" alias="dynamic1" />
</assemblies>
<typeDefinitions>
</typeDefinitions>
<parameterSerializers>
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<boolean name="failCustomServiceValidation" value="false"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="SharedServices.Interfaces.IDbConnection" >
<valueImplementation scope="singleton">
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="MainServer"/>
<string name="databaseName" value="DB1"/>
<string name="userName" value="sa"/>
<string name="password" value="password1"/>
</parameters>
</constructedValue>
</valueImplementation>
</service>
</services>
<autoGeneratedServices>
<!--Interface specified in autoServiceCustom is auto-implemented by implementation of
IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator
that is specified in autoServiceCodeGenerator element.-->
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IAuthorsRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="15" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IBooksRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="25" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.DataRepositories.IAuthorBooksRepository">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator">
<parameters>
<int32 name="someDemoConstructorParameter" value="35" />
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
<!--Custom auto service to test failures-->
<autoServiceCustom interface="IoC.Configuration.Tests.AutoServiceCustom.ClassesForFailureTests.DogAbstr">
<autoServiceCodeGenerator>
<constructedValue type="IoC.Configuration.Tests.AutoServiceCustom.ClassesForFailureTests.CustomAutoServiceCodeGeneratorForFailureTests" >
<parameters>
<boolean name="simulateValidateFails" value="false"/>
<boolean name="simulateValidateOnIoCContainerLoadedFails" value="false"/>
<boolean name="simulateGenerateCSharpFailure" value="false"/>
<boolean name="simulateAssemblyBuildFailure" value="false"/>
</parameters>
</constructedValue>
</autoServiceCodeGenerator>
</autoServiceCustom>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_proxyService.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_proxyService.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_ProxyServiceTests"/>
<plugins
pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1"/>
<plugin name="Plugin2" enabled="true"/>
<plugin name="Plugin3" enabled="false"/>
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs"/>
<probingPath
path="TestFiles\ContainerImplementations\Autofac"/>
<probingPath
path="TestFiles\ContainerImplementations\Ninject"/>
<probingPath
path="TestFiles\DynamicallyLoadedDlls"/>
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext"/>
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext"/>
<assembly name="TestProjects.Modules" alias="modules"/>
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1"/>
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2"/>
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1"/>
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2"/>
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3"/>
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1"/>
<assembly name="TestProjects.SharedServices" alias="shared_services"/>
<assembly name="IoC.Configuration.Tests" alias="tests"/>
</assemblies>
<typeDefinitions>
<typeDefinition alias="IAppData" type="IoC.Configuration.Tests.ProxyService.Services.IAppData"/>
<typeDefinition alias="AppData" type="IoC.Configuration.Tests.ProxyService.Services.AppData"/>
<typeDefinition alias="Guid" type="System.Guid"/>
<typeDefinition alias="ListOfInt" type="System.Collections.Generic.List[System.Int32]"/>
</typeDefinitions>
<parameterSerializers>
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<!-- TODO:-->
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<constructedValue name="DefaultAppData" typeRef="AppData">
<injectedProperties>
<object name="ApplicationId" typeRef="Guid" value="09E7ABD4-1BA1-4683-BEF5-EFA8266D7308"/>
<string name="Name" value="Default Application"/>
</injectedProperties>
</constructedValue>
</settings>
<dependencyInjection>
<modules>
<!--<module type="IoC.Configuration.Tests.AutoService.AutoServiceTestsModule" />-->
</modules>
<services>
<!--IoC.Configuration.Tests.ProxyService.Services.IAppManager will be resolved
by resolving IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension.-->
<proxyService type="IoC.Configuration.Tests.ProxyService.Services.IAppManager">
<serviceToProxy type="IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension"/>
</proxyService>
<!--IoC.Configuration.Tests.ProxyService.Services.IAppManager2 will also be resolved to
IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension.-->
<proxyService type="IoC.Configuration.Tests.ProxyService.Services.IAppManager2">
<serviceToProxy type="IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension"/>
</proxyService>
<!--
AppManagerUser has a constructor with parameter of type IAppManager.
Since we have a proxyService element that resolves IAppManager to IAppManager_Extension,
the object injected into constructor will be resolved by resolving the service IAppManager_Extension.
IAppManager_Extension is auto-implemented in autoGeneratedServices element, however, it
can have regular implementation in code as well.
-->
<selfBoundService type="IoC.Configuration.Tests.ProxyService.Services.AppManagerUser" scope="singleton"/>
<!--
AppManagerUser2 has a constructor with parameter of type IAppManager2.
Since we have a proxyService element that resolves IAppManager2 to IAppManager_Extension,
the object injected into will be resolved by resolving the service IAppManager_Extension.
-->
<selfBoundService type="IoC.Configuration.Tests.ProxyService.Services.AppManager2User" scope="singleton"/>
<service type="IoC.Configuration.Tests.ProxyService.Services.IInterface1_Extension">
<implementation type="IoC.Configuration.Tests.ProxyService.Services.Interface1_Extension_Impl1"
scope="singleton"/>
</service>
<!--IoC.Configuration.Tests.ProxyService.Services.IInterface1 will be resolved by
resolving IoC.Configuration.Tests.ProxyService.Services.IInterface1_Extension.-->
<proxyService type="IoC.Configuration.Tests.ProxyService.Services.IInterface1">
<serviceToProxy type="IoC.Configuration.Tests.ProxyService.Services.IInterface1_Extension"/>
</proxyService>
<!--
Interface1User has a constructor with parameter of type IInterface1.
Since we have a proxyService element that resolves IInterface1 to IInterface1_Extension,
the object injected into constructor will be resolved by resolving the service IInterface1_Extension.
-->
<selfBoundService type="IoC.Configuration.Tests.ProxyService.Services.Interface1User" scope="singleton"/>
<!--System.Collections.Generic.List<System.Int32> will be bound to a list of three integers: 19, 2, 17-->
<service typeRef="ListOfInt">
<valueImplementation scope="singleton">
<collection>
<int32 value="19"/>
<int32 value="2"/>
<int32 value="17"/>
</collection>
</valueImplementation>
</service>
<!--Resolving System.Collections.Generic.IEnumerable<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IEnumerable[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--Resolving System.Collections.Generic.IReadOnlyList<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IReadOnlyList[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--Resolving System.Collections.Generic.IList<System.Int32> will return the same value as resolving
System.Collections.Generic.List<System.Int32>-->
<proxyService type="System.Collections.Generic.IList[System.Int32]">
<serviceToProxy typeRef="ListOfInt"/>
</proxyService>
<!--START-Test binding an interface to the ame instance to which a self-bound class is bound-->
<selfBoundService type="SharedServices.Implementations.Interface13_Impl1" scope="singleton" />
<!--NOTE: Using proxyService allows us to bind
SharedServices.Interfaces.IInterface13 to the same instance of SharedServices.Implementations.Interface13_Impl1 to which
SharedServices.Implementations.Interface13_Impl1 was bound using selfBoundService element.
If we used "implementation" element under service and specified a type SharedServices.Implementations.Interface13_Impl1
instead of using "proxyService", then SharedServices.Interfaces.IInterface13 would have been
bound to a different instance of SharedServices.Implementations.Interface13_Impl1. In other words resolving
SharedServices.Implementations.Interface13_Impl1 and SharedServices.Interfaces.IInterface13 would have resulted in
different instances of SharedServices.Implementations.Interface13_Impl1.
Using "proxyService" element might be useful when we have module(s) that scan assemblies and self-binds
non-abstract classes. In this cases we can use "proxyService" element if we want the interface
specified in "proxyService" element to resolve to exactly the same value to which the self bound class is bound.
-->
<proxyService type="SharedServices.Interfaces.IInterface13">
<serviceToProxy type="SharedServices.Implementations.Interface13_Impl1"/>
</proxyService>
<service type="SharedServices.Interfaces.IInterface14">
<implementation type="SharedServices.Implementations.Interface14_Impl1" scope="singleton" />
</service>
<!--END-Test binding an interface to the ame instance to which a self-bound class is bound-->
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<!--IAppManager_Extension extends IAppManager, so can implement properties and method in both
IAppManager and IAppManager_Extension
-->
<autoService interface="IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension">
<!-- IAppData IAppManager.GetApp(System.Guid applicationId):-->
<autoMethod name="GetApp"
returnTypeRef="IAppData"
reuseValue="true">
<methodSignature>
<object typeRef="Guid"/>
</methodSignature>
<if parameter1="3907D19A-E53C-4471-B1B1-A3E0C36482B6">
<constructedValue typeRef="AppData">
<injectedProperties>
<object name="ApplicationId" typeRef="Guid"
value="3907D19A-E53C-4471-B1B1-A3E0C36482B6"/>
<string name="Name" value="App1"/>
</injectedProperties>
</constructedValue>
</if>
<if parameter1="09E7ABD4-1BA1-4683-BEF5-EFA8266D7308">
<constructedValue typeRef="AppData">
<injectedProperties>
<object name="ApplicationId" typeRef="Guid"
value="09E7ABD4-1BA1-4683-BEF5-EFA8266D7308"/>
<string name="Name" value="App2"/>
</injectedProperties>
</constructedValue>
</if>
<default>
<settingValue settingName="DefaultAppData"/>
</default>
</autoMethod>
<!---bool IAppManager2.IsPublicApp(Guid applicationId):-->
<autoMethod name="IsPublicApp" returnType="System.Boolean">
<methodSignature>
<object paramName="applicationId" typeRef="Guid"/>
</methodSignature>
<if parameter1="09E7ABD4-1BA1-4683-BEF5-EFA8266D7308">
<boolean value="true"/>
</if>
<default>
<boolean value="false"/>
</default>
</autoMethod>
<!-- IAppData IAppManager_Extension.DefaultApp { get; }-->
<autoProperty name="DefaultApp" returnTypeRef="IAppData">
<settingValue settingName="DefaultAppData"/>
</autoProperty>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="TestPluginAssembly1.Interfaces.IDemoProxyService_Extension">
<implementation type="TestPluginAssembly1.Implementations.DemoProxyService_Extension_Impl"
scope="singleton"/>
</service>
<!--TestPluginAssembly1.Interfaces.IDemoProxyServicewill be resolved by
resolving TestPluginAssembly1.Interfaces.IDemoProxyService_Extension.-->
<proxyService type="TestPluginAssembly1.Interfaces.IDemoProxyService">
<serviceToProxy type="TestPluginAssembly1.Interfaces.IDemoProxyService_Extension"/>
</proxyService>
<!--
DemoProxyServiceUser has a constructor with parameter of type IDemoProxyService.
Since we have a proxyService element that resolves IDemoProxyService to IDemoProxyService_Extension,
the object injected into constructor will be resolved by resolving the service IDemoProxyService_Extension.
-->
<selfBoundService type="TestPluginAssembly1.Implementations.DemoProxyServiceUser"
scope="singleton"/>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true"/>
<double name="param2" value="25.3"/>
<string name="param3" value="String value"/>
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_valueImplementation.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_valueImplementation.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_ValueImplementationTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" enabled="true" />
<plugin name="Plugin3" enabled="false" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
<typeDefinition alias="IAppInfo" type="IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo" />
<typeDefinition alias="AppInfo" type="IoC.Configuration.Tests.ValueImplementation.Services.AppInfo" />
</typeDefinitions>
<parameterSerializers>
<serializers>
<parameterSerializer type="TestPluginAssembly1.Implementations.DoorSerializer" />
</serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<int32 name="defaultAppId" value="38" />
<string name="defaultAppDescription" value="Deafult App"/>
<!--<constructedValue name="defaultAppInfo" typeRef="AppInfo">
<parameters>
<int32 name="appId" value="37"/>
</parameters>
</constructedValue>-->
</settings>
<dependencyInjection>
<modules>
<!--<module type="IoC.Configuration.Tests.AutoService.AutoServiceTestsModule" />-->
<module type="IoC.Configuration.Tests.ValueImplementation.Module1" />
</modules>
<services>
<!--int value is bound to the value of setting defaultAppId.-->
<service type="System.Int32">
<valueImplementation scope="singleton">
<settingValue settingName="defaultAppId"/>
</valueImplementation>
</service>
<!--Service IAppInfo is bound to AppInfo constructed using constructedValue element.-->
<service typeRef="IAppInfo">
<valueImplementation scope="transient">
<constructedValue typeRef="AppInfo">
<parameters>
<settingValue name="appId" settingName="defaultAppId" />
</parameters>
</constructedValue>
</valueImplementation>
</service>
<!--System.Double value is bound to 3.5.-->
<service type="System.Double">
<valueImplementation scope="singleton">
<!--object elements value is initialized by a serializer of type OROptimizer.Serializer.ITypeBasedSimpleSerializer
that can be registered in section parameterSerializers.
IoC.Configuration provides number of default serializers for some types.
The out of the box serializer for System.Double is OROptimizer.Serializer.TypeBasedSimpleSerializerDouble which is available
in Nuget package OROptimizer.Shared.
-->
<object type="System.Double" value="3.5"/>
</valueImplementation>
</service>
<!--Examples of using classMember element in valueImplementation-->
<service type="IoC.Configuration.Tests.ValueImplementation.Services.IDbConnectionProvider">
<implementation type="IoC.Configuration.Tests.ValueImplementation.Services.DbConnectionProvider" scope="singleton">
<parameters>
<string name="serverName" value="SqlServer1"/>
<string name="databaseName" value="Db1"/>
<string name="userName" value="restrictedUser"/>
<string name="password" value="safePassword123"/>
</parameters>
</implementation>
</service>
<!--Type SharedServices.Interfaces.IDbConnection will be bound to a vlue returned by call to
IoC.Configuration.Tests.ValueImplementation.Services.IDbConnectionProvider.GetDbConnection().
Since IDbConnectionProvider.GetDbConnection() is non-static, an instance of IDbConnectionProvider will be resolved
from DI container, and method GetDbConnection() will be called using the resolved instance
-->
<service type="SharedServices.Interfaces.IDbConnection">
<valueImplementation scope="transient">
<classMember class="IoC.Configuration.Tests.ValueImplementation.Services.IDbConnectionProvider" memberName="GetDbConnection"/>
</valueImplementation>
</service>
<service type="SharedServices.Interfaces.IActionValidator">
<valueImplementation scope="transient">
<classMember class="IoC.Configuration.Tests.ValueImplementation.Services.StaticMethods" memberName="GetActionValidator"/>
</valueImplementation>
</service>
<!--Service IReadOnlyList<IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo> is bound to a collection
specified in valueImplementation element.-->
<service type="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo]">
<valueImplementation scope="singleton" >
<collection>
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="paramId" value="1"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="paramId" value="2"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
<!--
The service below will be ignored, since registerIfNotRegistered is true, and we already registered a binding for
System.Collections.Generic.List<IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo> in
IoC.Configuration.Tests.ValueImplementation.Module1.
-->
<service type="System.Collections.Generic.List[IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo]"
registerIfNotRegistered="true">
<valueImplementation scope="singleton" >
<collection>
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="paramId" value="15"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="System.Collections.Generic.IReadOnlyList[TestPluginAssembly1.Interfaces.IDoor]">
<valueImplementation scope="singleton">
<collection>
<object type="TestPluginAssembly1.Interfaces.IDoor" value="4359924, 80.3"/>
<constructedValue type="TestPluginAssembly1.Implementations.Door">
<parameters>
<int32 name="color" value="4359934"/>
<double name="height" value="85.2" />
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true" />
<double name="param2" value="25.3" />
<string name="param3" value="String value" />
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_collection.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_collection.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_CollectionTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" />
<plugin name="Plugin3" enabled="false" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
<typeDefinition alias="IInterface1" type="SharedServices.Interfaces.IInterface1"></typeDefinition>
<typeDefinition alias="Interface1_Impl" type="IoC.Configuration.Tests.Collection.Services.Interface1_Impl"></typeDefinition>
</typeDefinitions>
<parameterSerializers>
<!--
Use parameters element to specify constructor parameters, if the type specified in 'serializerAggregatorType' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<constructedValue name="DefaultDBConnection" type="SharedServices.Implementations.SqliteDbConnection"
assembly="shared_services">
<parameters>
<string name="filePath" value="c:\SQLiteFiles\MySqliteDb.sqlite"/>
</parameters>
</constructedValue>
<constructedValue name="DefaultInterface1Value" typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="21"/>
</parameters>
</constructedValue>
<constructedValue name="Collections" type="IoC.Configuration.Tests.Collection.Services.DemoCollectionInjection">
<parameters>
<!--Demo of injecting a collection into a constructor of DemoCollectionInjection in constructedValue element-->
<collection name="intValues" collectionType="readOnlyList" itemType="System.Int32">
<int32 value="17"/>
<int32 value="14"/>
</collection>
</parameters>
<injectedProperties>
<!--Demo of injecting a collection into a property of DemoCollectionInjection in constructedValue element.-->
<collection name="Texts" collectionType="readOnlyList" itemType="System.String">
<string value="Microsoft"/>
<string value="Google"/>
<string value="Amazon"/>
</collection>
</injectedProperties>
</constructedValue>
</settings>
<dependencyInjection>
<modules>
<module type="IoC.Configuration.Tests.Collection.Module1">
<parameters>
<collection name="values" collectionType="enumerable" itemType="System.Int32">
<int32 value="5"/>
<int32 value="7"/>
</collection>
</parameters>
</module>
</modules>
<services>
<service type="SharedServices.Interfaces.IInterface1">
<implementation type="IoC.Configuration.Tests.Collection.Services.Interface1_Impl" scope="singleton">
<parameters>
<int32 name="param1" value="37"/>
</parameters>
</implementation>
</service>
<!--Demo of collection element used as an implementation for a service of collection type.-->
<service type="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IDbConnection]">
<valueImplementation scope="singleton">
<collection>
<settingValue settingName="DefaultDBConnection"/>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2012"/>
<string name="databaseName" value="DB1"/>
<string name="userName" value="user1"/>
<string name="password" value="password123"/>
</parameters>
</constructedValue>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2016"/>
<string name="databaseName" value="DB2"/>
<string name="userName" value="user2"/>
<string name="password" value="password456"/>
</parameters>
</constructedValue>
<!--This value will be added to collection since Plugin1 is enabled-->
<constructedValue type="TestPluginAssembly1.Implementations.MySqlDbConnection">
<parameters>
<string name="connectionString" value="user=User1;password=123"/>
</parameters>
</constructedValue>
<!--This value will not be added to collection since Plugin3 is disabled-->
<constructedValue type="TestPluginAssembly3.Implementations.OracleDbConnection" >
<parameters>
<string name="connectionString" value="user=User1;password=123"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
<!--Demo of collection element used as an implementation for a service of array type.-->
<!--The service type below is similar to C# type IoC.Configuration.Tests.Collection.Services.TestLocalTypesClass.IInterface1[]-->
<service type="IoC.Configuration.Tests.Collection.Services.TestLocalTypesClass.IInterface1#">
<valueImplementation scope="transient">
<collection>
<constructedValue type="IoC.Configuration.Tests.Collection.Services.TestLocalTypesClass.Interface1_Impl1">
<parameters>
<int32 name="value" value="13"/>
</parameters>
</constructedValue>
<constructedValue type="IoC.Configuration.Tests.Collection.Services.TestLocalTypesClass.Interface1_Impl1">
<parameters>
<int32 name="value" value="17"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
<selfBoundService type="IoC.Configuration.Tests.Collection.Services.CollectionsTestClass1" scope="singleton" >
<parameters>
<!--Demo of collection element used as a constructor parameter.-->
<collection name="readOnlyListParam" collectionType="readOnlyList" itemType="System.Int32">
<int32 value="17"/>
<int32 value="24"/>
<int32 value="27"/>
</collection>
<!--Demo of collection element used as a constructor parameter.-->
<collection name="arrayParam" collectionType="array" itemTypeRef="IInterface1">
<injectedObject typeRef="IInterface1"/>
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="29"/>
</parameters>
</constructedValue>
</collection>
</parameters>
<injectedProperties>
<!--Demo of collection element used to initialize the value of injected property.-->
<collection name="EnumerableValues" collectionType="enumerable" itemType="SharedServices.Interfaces.IInterface1" >
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="18"/>
</parameters>
</constructedValue>
<settingValue settingName="DefaultInterface1Value"/>
<injectedObject typeRef="IInterface1"/>
</collection>
<!--Demo of collection element used to initialize the value of injected property.-->
<collection name="ListValues" collectionType="list" itemTypeRef="IInterface1">
<injectedObject typeRef="IInterface1"/>
<settingValue settingName="DefaultInterface1Value"/>
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="139"/>
</parameters>
</constructedValue>
</collection>
</injectedProperties>
</selfBoundService>
</services>
<autoGeneratedServices>
<!--Demo of collection element used in auto-implemented method and property return values.-->
<autoService interface="IoC.Configuration.Tests.Collection.Services.IAutoService1">
<autoMethod name="GetAllActionIds" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]">
<methodSignature>
<int32 paramName="appId"/>
</methodSignature>
<if parameter1="3">
<collection>
<int32 value="27"/>
<int32 value="17"/>
</collection>
</if>
<default>
<collection>
<int32 value="13"/>
<int32 value="27"/>
<int32 value="17"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true" />
<double name="param2" value="25.3" />
<string name="param3" value="String value" />
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_constructedValue.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_constructedValue.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory. constructed
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_constructedValueTests" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
<typeDefinition alias="IAppInfo" type="IoC.Configuration.Tests.ConstructedValue.Services.IAppInfo" />
<typeDefinition alias="AppInfo" type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfo" />
</typeDefinitions>
<parameterSerializers>
<serializers>
<!--Serializer IoC.Configuration.Tests.ConstructedValue.Services.AppInfoSerializer will be used to de-serialize value
provided in element <object> into instance of type IoC.Configuration.Tests.ConstructedValue.Services.AppInfo-->
<parameterSerializer type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfoSerializer">
<parameters>
<!--Demo of using constructedValue to inject constructor parameter value into parameter serializer.-->
<constructedValue name="appDescriptionFormatter" type="IoC.Configuration.Tests.ConstructedValue.Services.AppDescriptionFormatter">
<parameters>
<string name="prefixToAddToDescription" value="AppData::"/>
</parameters>
<injectedProperties>
<string name="PostfixToAddToDescription" value="::AppDataEnd"/>
</injectedProperties>
</constructedValue>
</parameters>
</parameterSerializer>
</serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<object name="App1" typeRef="IAppInfo" value="1, App 1"/>
<!--Demo of constructedValue in settings element. -->
<constructedValue name="App2" typeRef="AppInfo" >
<parameters>
<int32 name="Id" value="2"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 2"/>
</injectedProperties>
</constructedValue>
<!--Demo of constructedValue used as a parameter value in another constructedValue.
Constructing DecoratedAppInfo setting below is similar to creating an instance of AppInfoDecorator using the following C# code:
new AppInfoDecorator(new AppInfoDecorator(new AppInfo(25, "App 25")))
-->
<constructedValue name="DecoratedAppInfo" type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfoDecorator">
<parameters>
<constructedValue name="appInfo" type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfoDecorator">
<parameters>
<constructedValue name="appInfo" typeRef="AppInfo">
<parameters>
<int32 name="id" value="25"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 25"/>
</injectedProperties>
</constructedValue>
</parameters>
</constructedValue>
</parameters>
</constructedValue>
</settings>
<dependencyInjection>
<modules>
<module type="IoC.Configuration.Tests.ConstructedValue.Module1">
<parameters>
<!--Demo of constructedValue to inject constructor parameter and property into module. -->
<constructedValue name="appInfo" typeRef="AppInfo">
<parameters>
<int32 name="id" value="3"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 3"/>
</injectedProperties>
</constructedValue>
</parameters>
</module>
</modules>
<services>
<service typeRef="IAppInfo">
<valueImplementation scope="singleton">
<!--Demo of constructedValue to provide an implementation for a service under valueImplementation element.-->
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="id" value="8"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 8"/>
</injectedProperties>
</constructedValue>
</valueImplementation>
</service>
<service type="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.ConstructedValue.Services.IAppInfo]">
<valueImplementation scope="singleton">
<collection>
<!--Demo of constructedValue in collection-->
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="id" value="10"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 10"/>
</injectedProperties>
</constructedValue>
<settingValue settingName="App1"/>
</collection>
</valueImplementation>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="IoC.Configuration.Tests.ConstructedValue.Services.IAppInfoFactory">
<autoProperty name="DefaultAppInfo" returnTypeRef="IAppInfo">
<!--Demo of constructedValue in autoProperty-->
<constructedValue typeRef="AppInfo" >
<parameters>
<int32 name="id" value="11"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 11"/>
</injectedProperties>
</constructedValue>
</autoProperty>
<!--Demo of constructedValue in autoMethod-->
<autoMethod name="CreateAppInfo" returnTypeRef="IAppInfo">
<default>
<constructedValue typeRef="AppInfo" >
<parameters>
<int32 name="id" value="12"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 12"/>
</injectedProperties>
</constructedValue>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
<startupAction type="IoC.Configuration.Tests.ConstructedValue.Services.StartupAction1">
<parameters>
<constructedValue name="appInfo" typeRef="AppInfo">
<parameters>
<int32 name="id" value="9"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 9"/>
</injectedProperties>
</constructedValue>
</parameters>
</startupAction>
</startupActions>
<pluginsSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_classMember.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_classMember.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_ClassMemberTests"/>
<plugins
pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1"/>
<plugin name="Plugin2" enabled="true"/>
<plugin name="Plugin3" enabled="false"/>
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs"/>
<probingPath
path="TestFiles\ContainerImplementations\Autofac"/>
<probingPath
path="TestFiles\ContainerImplementations\Ninject"/>
<probingPath
path="TestFiles\DynamicallyLoadedDlls"/>
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext"/>
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext"/>
<assembly name="TestProjects.Modules" alias="modules"/>
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1"/>
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2"/>
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1"/>
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2"/>
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3"/>
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1"/>
<assembly name="TestProjects.SharedServices" alias="shared_services"/>
<assembly name="IoC.Configuration.Tests" alias="tests"/>
</assemblies>
<typeDefinitions>
<typeDefinition alias="ConstAndStaticAppIds"
type="IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds"/>
<typeDefinition alias="IAppIds" type="IoC.Configuration.Tests.ClassMember.Services.IAppIds"/>
<typeDefinition alias="AppTypes" type="IoC.Configuration.Tests.ClassMember.Services.AppTypes"/>
<typeDefinition alias="AppInfo" type="IoC.Configuration.Tests.ClassMember.Services.AppInfo"/>
<typeDefinition alias="StaticMethodsWithParameters"
type="IoC.Configuration.Tests.ClassMember.Services.StaticMethodsWithParameters"/>
</typeDefinitions>
<parameterSerializers>
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
</settings>
<dependencyInjection>
<modules>
<!--<module type="IoC.Configuration.Tests.AutoService.AutoServiceTestsModule" />-->
<module type="IoC.Configuration.Tests.ClassMember.Module1">
<parameters>
<classMember name="param1" classRef="ConstAndStaticAppIds" memberName="DefaultAppId"/>
<classMember name="param2" classRef="StaticMethodsWithParameters" memberName="GetString">
<parameters>
<int32 name="intParam" value="5"/>
<string name="strParam" value="Value 1"/>
</parameters>
</classMember>
</parameters>
</module>
</modules>
<services>
<service type="System.Int32">
<valueImplementation scope="singleton">
<!--Example of classMember in valueImplementation. Since IAppIds.DefaultAppId is non-static,
IAppIds will be resolved from dependency injection container, and the value of property DefaultAppId of
resolved object will be bound to System.Int32
-->
<classMember classRef="IAppIds" memberName="DefaultAppId"/>
</valueImplementation>
</service>
<!--<service type="System.String">
<valueImplementation scope="singleton">
<object type="System.String" value="Test"/>
</valueImplementation>
</service>-->
<service type="System.String">
<valueImplementation scope="singleton">
<!--Example of classMember in valueImplementation. Since IAppIds.DefaultAppDescription is non-static,
IAppIds will be resolved from dependency injection container, and the value of property DefaultAppDescription of
resolved object will be bound to System.Int32
-->
<classMember classRef="IAppIds" memberName="DefaultAppDescription"/>
<!-- <object type="System.String" value="Test" />-->
</valueImplementation>
</service>
<service type="IoC.Configuration.Tests.ClassMember.Services.IAppInfo">
<!--The DI will try to construct IoC.Configuration.Tests.ClassMember.Services.AppInfo using the constructor
with max number of parameters: AppInfo(int appId, string appDescription).
Since we bound System.Int32, and System.String to IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId,
and IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppDescription, the values of injected
appId and appDescription will be IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId and
IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppDescription.
-->
<implementation typeRef="AppInfo" scope="singleton">
</implementation>
</service>
<service type="System.Collections.Generic.IReadOnlyList[System.Int32]">
<valueImplementation scope="singleton">
<collection>
<!--Demo of classMember in collection element.-->
<classMember classRef="ConstAndStaticAppIds" memberName="AppId1"/>
<classMember classRef="IAppIds" memberName="DefaultAppId"/>
</collection>
</valueImplementation>
</service>
<service type="IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory">
<implementation type="IoC.Configuration.Tests.ClassMember.Services.AppInfoFactory" scope="singleton"/>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interfaceRef="IAppIds">
<autoProperty name="DefaultAppId" returnType="System.Int32">
<!--Example of using classMember attribute in auto property.-->
<classMember class="System.Int32" memberName="MaxValue"/>
</autoProperty>
<autoProperty name="DefaultAppDescription" returnType="System.String">
<!--Example of using classMember attribute in auto property.-->
<classMember classRef="ConstAndStaticAppIds" memberName="DefaultAppDescription"/>
</autoProperty>
</autoService>
<autoService interface="IoC.Configuration.Tests.ClassMember.Services.IAppInfos">
<autoProperty name="AllAppInfos"
returnType="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.ClassMember.Services.IAppInfo]">
<collection>
<constructedValue typeRef="AppInfo">
<parameters>
<!--Property IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId is non-static, therefore
IoC.Configuration.Tests.ClassMember.Services.IAppIds will be resolved from dependency injection container,
and the value of property DefaultAppId in resolved object will be used as parameter value appId-->
<classMember name="appId" classRef="IAppIds" memberName="DefaultAppId"/>
</parameters>
<injectedProperties>
<!--Property IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId is non-static, therefore
IoC.Configuration.Tests.ClassMember.Services.IAppIds will be resolved from dependency injection container,
and the value of property DefaultAppId in resolved object will be used as parameter value appId-->
<classMember name="AppDescription" classRef="IAppIds"
memberName="DefaultAppDescription"/>
</injectedProperties>
</constructedValue>
<!--
An example of calling a non static factory method to create an instance of IAppInfo.
Since method IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory.CreateAppInfo(appId, appDescription)
is non-static, an instance of IAppInfoFactory will be resolved using the DI container.
Also, since IAppInfoFactory is an interface, a binding for IAppInfoFactory should be configured in configuration
file or in some module.
-->
<classMember class="IoC.Configuration.Tests.ClassMember.Services.IAppInfoFactory"
memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1258"/>
<string name="appDescription" value="App info created with non-static method call."/>
</parameters>
</classMember>
<!--
An example of calling a static factory method to create an instance of IAppInfo.
-->
<classMember class="IoC.Configuration.Tests.ClassMember.Services.StaticAppInfoFactory"
memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1259"/>
<string name="appDescription" value="App info created with static method call."/>
</parameters>
</classMember>
<constructedValue typeRef="AppInfo">
<parameters>
<!--Method IoC.Configuration.Tests.ClassMember.Services.IAppIds.GetAppId() is non-static, therefore
IoC.Configuration.Tests.ClassMember.Services.IAppIds will be resolved from dependency injection container,
and the value returned by method IAppIds.GetAppId() will be used as parameter value appId-->
<classMember name="appId" classRef="IAppIds" memberName="GetAppId"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--Variable IoC.Configuration.Tests.ClassMember.Services.AppIdVars.NonStaticAppIdVar is non-static/non-constant, therefore
IoC.Configuration.Tests.ClassMember.Services.AppIdVars will be resolved from dependency injection container,
and the value variable NonStaticAppIdVarin resolved object will be used as parameter value appId
NOTE, no need to add a self bound service for IoC.Configuration.Tests.ClassMember.Services.AppIdVars, since
IoC.Configuration will generated one.
-->
<classMember name="appId" class="IoC.Configuration.Tests.ClassMember.Services.AppIdVars"
memberName="NonStaticAppIdVar"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId1 is a constant value.-->
<classMember name="appId" classRef="ConstAndStaticAppIds" memberName="AppId1"/>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.App1Description is a constant value.-->
<classMember name="appDescription" classRef="ConstAndStaticAppIds"
memberName="App1Description"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId2 is a static variable.-->
<classMember name="appId" classRef="ConstAndStaticAppIds" memberName="AppId2"/>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.App2Description is a static variable.-->
<classMember name="appDescription" classRef="ConstAndStaticAppIds"
memberName="App2Description"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId3 is a static property.-->
<classMember name="appId" classRef="ConstAndStaticAppIds" memberName="AppId3"/>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.GetApp3Description is a static function-->
<classMember name="appDescription" classRef="ConstAndStaticAppIds"
memberName="GetApp3Description"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.GetAppId4() is a static method.-->
<classMember name="appId" classRef="ConstAndStaticAppIds" memberName="GetAppId4"/>
<string name="appDescription" value="App 4"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<!--IoC.Configuration.Tests.ClassMember.Services.AppTypes.App1 is an enum value.-->
<classMember name="appId" classRef="AppTypes" memberName="App1"/>
</parameters>
</constructedValue>
</collection>
</autoProperty>
</autoService>
<autoService interface="IoC.Configuration.Tests.ClassMember.Services.IAppIdToPriority">
<autoMethod name="GetPriority" returnType="System.Int32">
<methodSignature>
<int32 paramName="appId"/>
</methodSignature>
<!--Property IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId is non-static, therefore
IoC.Configuration.Tests.ClassMember.Services.IAppIds will be resolved from dependency injection container,
and the value of property DefaultAppId in resolved object will be used in if condition-->
<if parameter1="_classMember:IAppIds.DefaultAppId">
<int32 value="14"/>
</if>
<!--Method IoC.Configuration.Tests.ClassMember.Services.IAppIds.GetAppId() is non-static, therefore
IoC.Configuration.Tests.ClassMember.Services.IAppIds will be resolved from dependency injection container,
and the value returned by method IAppIds.GetAppId() will be used in if condition-->
<if parameter1="_classMember:IAppIds.GetAppId">
<int32 value="25"/>
</if>
<!--Variable IoC.Configuration.Tests.ClassMember.Services.AppIdVars.NonStaticAppIdVar is non-static/non-constant, therefore
IoC.Configuration.Tests.ClassMember.Services.AppIdVars will be resolved from dependency injection container,
and the value variable NonStaticAppIdVarin resolved object will be used in if condition.
NOTE, no need to add a self bound service for IoC.Configuration.Tests.ClassMember.Services.AppIdVars, since
IoC.Configuration will generated one. -->
<if parameter1="_classMember:IoC.Configuration.Tests.ClassMember.Services.AppIdVars.NonStaticAppIdVar">
<int32 value="23"/>
</if>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId1 is a constant value.-->
<if parameter1="_classMember:ConstAndStaticAppIds.AppId1">
<int32 value="4"/>
</if>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId2 is a static variable.-->
<if parameter1="_classMember:ConstAndStaticAppIds.AppId2">
<int32 value="7"/>
</if>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.AppId3 is a static property.-->
<if parameter1="_classMember:ConstAndStaticAppIds.AppId3">
<int32 value="8"/>
</if>
<!--IoC.Configuration.Tests.ClassMember.Services.ConstAndStaticAppIds.GetAppId4() is a static method.-->
<if parameter1="_classMember:ConstAndStaticAppIds.GetAppId4">
<int32 value="5"/>
</if>
<default>
<int32 value="0"/>
</default>
</autoMethod>
<autoMethod name="GetPriority" returnType="System.Int32">
<methodSignature>
<object paramName="appType" type="IoC.Configuration.Tests.ClassMember.Services.AppTypes"/>
</methodSignature>
<!--Example of using _classMember in If statement to reference enum value.-->
<if parameter1="_classMember:IoC.Configuration.Tests.ClassMember.Services.AppTypes.App1">
<int32 value="8"/>
</if>
<!--Example of using _classMember in If statement to reference enum value.-->
<if parameter1="_classMember:IoC.Configuration.Tests.ClassMember.Services.AppTypes.App2">
<int32 value="9"/>
</if>
<default>
<int32 value="1"/>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true"/>
<double name="param2" value="25.3"/>
<string name="param3" value="String value"/>
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
IoCConfiguration_settingValue_ReferencingInConfiguration.xml¶
This configuration file can be downloaded downloaded from IoCConfiguration_settingValue_ReferencingInConfiguration.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | <?xml version="1.0" encoding="utf-8"?>
<!--
The XML configuration file is validated against schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd,
which can be found in folder IoC.Configuration.Content in output directory.
The schema file can also be downloaded from
http://oroptimizer.com/ioc.configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd or in source code
project in Github.com.
To use Visual Studio code completion based on schema contents, right click Properties on this file in Visual Studio, and in Schemas
field pick the schema IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd.
Before running the tests make sure to execute IoC.Configuration\Tests\IoC.Configuration.Tests\PostBuildCommands.bat to copy the dlls into
folders specified in this configuration file.
Also, modify the batch file to copy the Autofac and Ninject assemblies from Nuget packages folder on machine, where the test is run.
-->
<iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<!--The application should have write permissions to path specified in appDataDir.
This is where dynamically generated DLLs are saved.-->
<!--NOTE: path should be an absolute path, or should be converted to absolute path by some implementation of
IoC.Configuration.AttributeValueTransformer.IAttributeValueTransformer. In this example the paths are converted by
IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.-->
<appDataDir
path="TestFiles\AutogeneratedDlls\DynamicFiles_SettingValue" />
<plugins pluginsDirPath="TestFiles\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\IoC.Configuration\Tests\IoC.Configuration.Tests\bin\TestFiles\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" enabled="true" />
<plugin name="Plugin3" enabled="false" />
</plugins>
<additionalAssemblyProbingPaths>
<probingPath
path="TestFiles\ThirdPartyLibs" />
<probingPath
path="TestFiles\ContainerImplementations\Autofac" />
<probingPath
path="TestFiles\ContainerImplementations\Ninject" />
<probingPath
path="TestFiles\DynamicallyLoadedDlls" />
</additionalAssemblyProbingPaths>
<assemblies>
<!--Assemblies should be in one of the following locations:
1) Executable's folder
2) In folder specified in additionalAssemblyProbingPaths element.
3) In one of the plugin folders specified in plugins element (only for assemblies with plugin attribute) -->
<!--
Use "overrideDirectory" attribute, to make the assembly path explicit, rather then searching for
an assembly in predefined folders, which also include probing paths specified in additionalAssemblyProbingPaths element.
-->
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1"
alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2"
alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1"
alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2"
alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.TestPluginAssembly3"
alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.ModulesForPlugin1"
alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
<typeDefinitions>
</typeDefinitions>
<parameterSerializers>
<serializers></serializers>
</parameterSerializers>
<!--The value of type attribute should be a type that implements
IoC.Configuration.DiContainer.IDiManager-->
<diManagers activeDiManagerName="Autofac">
<!-- TODO:-->
<diManager name="Ninject" type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac" type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
<!--
If settingsRequestor element is used, the type in type attribute should
specify a type that implements IoC.Configuration.ISettingsRequestor.
The implementation specifies a collection of required settings that should be present
in settings element.
Note, the type specified in type attribute is fully integrated into a dependency
injection framework. In other words, constructor parameters will be injected using
bindings specified in dependencyInjection element.
-->
<settings>
<int32 name="defaultAppId" value="7"/>
<string name="defaultAppDescr" value="Default App"/>
<int32 name="app1" value="37"/>
<string name="android" value="Android"/>
<int32 name="defaultInt" value="-1"/>
<!--This setting is redefined in plugin1 settings section to be of int type.
Any services that reference a setting with name defaultColor, will be referencing the setting
in plugin1
-->
<string name="defaultColor" value="Brown" />
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="System.Int32">
<valueImplementation scope="transient">
<!--Demo of using a setting value in valueImplementation.-->
<settingValue settingName="defaultInt"/>
</valueImplementation>
</service>
<service type="System.Collections.Generic.IReadOnlyList[System.Int32]">
<valueImplementation scope="singleton">
<collection>
<!--Example of using setting value in collection element-->
<settingValue settingName="defaultInt"/>
<settingValue settingName="app1"/>
<int32 value="78"/>
</collection>
</valueImplementation>
</service>
<service type="IoC.Configuration.Tests.SettingValue.Services.IAppInfo" >
<implementation type="IoC.Configuration.Tests.SettingValue.Services.AppInfo" scope="transient">
<parameters>
<!--Demo of using settingValue to inject value into an implementation constructor.-->
<settingValue name="appId" settingName="defaultAppId"/>
</parameters>
<injectedProperties>
<!--Demo of using settingValue to inject value into an implementation property.-->
<settingValue name="AppDescription" settingName="defaultAppDescr"/>
</injectedProperties>
</implementation>
</service>
<service type="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.SettingValue.Services.IAppInfo]">
<valueImplementation scope="singleton">
<collection>
<constructedValue type="IoC.Configuration.Tests.SettingValue.Services.AppInfo">
<parameters>
<!--Demo of using settingValue to inject a constructor parameter value in constructedValue element.-->
<settingValue name="appId" settingName="defaultAppId"/>
</parameters>
<injectedProperties>
<!--Demo of using settingValue to inject a property parameter value in constructedValue element.-->
<settingValue name="AppDescription" settingName="defaultAppDescr"/>
</injectedProperties>
</constructedValue>
</collection>
</valueImplementation>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="IoC.Configuration.Tests.SettingValue.Services.IAppIds">
<autoMethod name="GetDefaultAppId" returnType="System.Int32">
<default>
<settingValue settingName="defaultAppId"/>
</default>
</autoMethod>
<autoMethod name="GetAppIds" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]">
<methodSignature>
<string paramName="platformType"/>
</methodSignature>
<!--Demo of using the value of setting named "android" in if condition in autoMethod-->
<if parameter1="_settings:android">
<collection>
<!--Demo of setting value used as one of returned values in autoMethod if element.-->
<settingValue settingName="defaultAppId"/>
<settingValue settingName="app1"/>
<int32 value="9"/>
</collection>
</if>
<default>
<collection>
<!--Demo of setting value used as one of returned values in autoMethod default element.-->
<settingValue settingName="defaultAppId"/>
<int32 value="8"/>
</collection>
</default>
</autoMethod>
<autoProperty name="MainAppId" returnType="System.Int32">
<!--Demo of setting value used as return value of autoProperty element.-->
<settingValue settingName="defaultAppId"/>
</autoProperty>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
<startupActions>
</startupActions>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple">
</pluginImplementation>
<settings>
<!--This setting with string type is also defined in non-plugin section.
Since we re-defined the setting, any the references in plugin section to setting with name defaultColor,
will be referencing the setting redefined here.
-->
<int32 name="defaultColor" value="4997399" />
<int32 name="Int32Setting1" value="10"/>
<string name="StringSetting1" value="Some text"/>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
<service type="TestPluginAssembly1.Interfaces.IDoor">
<implementation type="TestPluginAssembly1.Implementations.Door" scope="transient">
<parameters>
<settingValue name="color" settingName="defaultColor"/>
<int32 name="height" value="80"/>
</parameters>
</implementation>
</service>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin2">
<pluginImplementation type="TestPluginAssembly2.Implementations.Plugin2" assembly="pluginassm2">
<parameters>
<boolean name="param1" value="true" />
<double name="param2" value="25.3" />
<string name="param3" value="String value" />
</parameters>
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
<pluginSetup plugin="Plugin3">
<pluginImplementation type="TestPluginAssembly3.Implementations.Plugin3" assembly="pluginassm3">
</pluginImplementation>
<settings>
</settings>
<dependencyInjection>
<modules>
</modules>
<services>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
</iocConfiguration>
|
Type Binding In Modules¶
- Type bindings can be specified either in IoC.Configuration module classes or in 3-rd party container modules, such as Autofac or Ninject modules.
Note
For details on how to specify type bindings in XML configuration file, see XML Configuration File.
- To load the modules, use one of the following techniques
- Specify the module types in iocConfiguration/dependencyInjection/modules/module elements in XML configuration file (if the configuration is loaded from XML configuration). See the following sections for more details on how to do this.
- Load the modules directly, without loading any XML Configuration file. The module classes are specified as parameters in chained methods. To see how this is done, refer to Loading from Modules.
Type Bindings in IoC.Configuration Modules¶
Type Bindings in Implementation of IoC.Configuration.DiContainer.IDiModule¶
Type bindings can be specified either in implementation of Load() method of interface IoC.Configuration.DiContainer.IDiModule, or in overridden method AddServiceRegistrations in IoC.Configuration.DiContainer.ModuleAbstr.
Note
IoC.Configuration.DiContainer.ModuleAbstr is an implementation of interface IoC.Configuration.DiContainer.IDiModule.
Here is an example of specifying type bindings in overridden AddServiceRegistrations() method in a sub-class of IoC.Configuration.DiContainer.ModuleAbstr.
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<Class1>().ToSelf()
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<IInterface1>().To<Interface1_Impl1>()
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<Class2>().ToSelf()
.SetResolutionScope(DiResolutionScope.Transient);
Bind<IInterface2>().To<Interface2_Impl1>()
.SetResolutionScope(DiResolutionScope.Transient);
Bind<Class3>().ToSelf()
.SetResolutionScope(DiResolutionScope.ScopeLifetime);
Bind<IInterface3>().To<Interface3_Impl1>()
.SetResolutionScope(DiResolutionScope.ScopeLifetime);
Bind<Class4>().ToSelf()
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<Class4>().ToSelf()
.SetResolutionScope(DiResolutionScope.Transient);
// The first binding should be with Singletone scope, and the second
// should with Transient, so that we can test that the first binding was used.
Bind<Class5>().OnlyIfNotRegistered()
.ToSelf().SetResolutionScope(DiResolutionScope.Singleton);
Bind<Class5>().OnlyIfNotRegistered()
.ToSelf().SetResolutionScope(DiResolutionScope.Transient);
// Only the first binding below will be registered.
Bind<IInterface4>().OnlyIfNotRegistered().To<Interface4_Impl1>()
.SetResolutionScope(DiResolutionScope.Transient);
Bind<IInterface4>().OnlyIfNotRegistered().To<Interface4_Impl2>()
.SetResolutionScope(DiResolutionScope.Singleton);
// Both binding below will be registered
Bind<IInterface5>().OnlyIfNotRegistered()
.To<Interface5_Impl1>()
.SetResolutionScope(DiResolutionScope.Transient);
Bind<IInterface5>().To<Interface5_Impl2>()
.SetResolutionScope(DiResolutionScope.Singleton);
// Test delegates and resolution using IDiContainer
Bind<IInterface6>()
.To(diContainer => new Interface6_Impl1(11, diContainer.Resolve<IInterface1>()));
#region Test circular references
Bind<ICircularReferenceTestInterface1>()
.To<CircularReferenceTestInterface1_Impl>()
.OnImplementationObjectActivated(
(diContainer, instance) =>
// Note, type of instance is the implementation type
// CircularReferenceTestInterface1_Impl. So we can use Property1 setter.
// ICircularReferenceTestInterface1 has only getter for Property1.
instance.Property1 = diContainer.Resolve<ICircularReferenceTestInterface2>())
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<ICircularReferenceTestInterface2>().To<CircularReferenceTestInterface2_Impl>()
.SetResolutionScope(DiResolutionScope.Singleton);
#endregion
}
}
Note
The examples below demonstrate dependency injection concepts supported by IoC.Configuration package. Services are resolved using an instance of IoC.Configuration.DiContainer.IDiContainer. To see how to create an instance of IoC.Configuration.DiContainer.IDiContainer, refer to sections Loading from XML Configuration File and Loading from Modules. In examples below, it is assumed that an instance of IoC.Configuration.DiContainer.IDiContainer, diContainer, was already creating using one of the techniques described in these sections.
Types of Bindings¶
Binding to Self¶
This binding type can be used to specify that the type will be re-solved to an instance of the same type.
Here is an example of this type of binding in overridden method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations():
protected override void AddServiceRegistrations()
{
Bind<Class1>().ToSelf()
.SetResolutionScope(DiResolutionScope.Singleton);
}
Example of resolving the service Class1. Note, in example we use IoC.Configuration.DiContainer.IDiContainer to resolve Class1 for demonstration purposes, however normally we would just use a constructor injection.
private void SelfBoundServiceDemo(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
var implementation = diContainer.Resolve<Class1>();
Assert.IsTrue(implementation.GetType() == typeof(Class1));
}
Binding to Type¶
This binding type can be used to specify that type will be bound to some other type, that is either the same type, implementation or sub-class of the type being re-solved.
Example of this type of binding in overridden method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations():
protected override void AddServiceRegistrations()
{
//...
Bind<IInterface2>().To<Interface2_Impl1>()
.SetResolutionScope(DiResolutionScope.Transient);
}
Example of resolving the service IInterface2.
private void BindToTypeDemo(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
var implementation = diContainer.Resolve<IInterface2>();
Assert.IsTrue(implementation.GetType() == typeof(Interface2_Impl1));
// Validate that the implementation is an instance of the resolved type.
Assert.IsInstanceOfType(implementation, typeof(IInterface2));
}
Binding to a Delegate¶
Type is resolved to an object returned by a delegate.
Note
The delegate that is used to create an instance of resolved type accepts as a parameter an instance of IoC.Configuration.DiContainer.IDiContainer. This parameter can be used to resolve other types, when constructing the object to return.
Example of this type of binding in overridden method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations():
protected override void AddServiceRegistrations()
{
//...
Bind<IInterface6>().To(
// The compiler will generate an error message if object of type IInterface6 is not assignable from an object of type Interface6_Impl1.
diContainer => new Interface6_Impl1(11, diContainer.Resolve<IInterface1>()));
}
Example of resolving the service IInterface6.
private void BindToAValueReturnedByDelegate(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
//...
var implementation = diContainer.Resolve<IInterface6>();
Assert.IsInstanceOfType(implementation, typeof(IInterface6));
}
Specifying Resolution Scope¶
For more details on resolution scope, refer to section Resolution Scopes. Here we will just mention that all three resolution scopes are supporetd in IoC.Configuration modules.
Here are some examples on how to specify the resolution scope in overridden method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations().
protected override void AddServiceRegistrations()
{
Bind<Class1>().ToSelf().SetResolutionScope(DiResolutionScope.Singleton);
Bind<IInterface4>().To<Interface4_Impl1>().SetResolutionScope(DiResolutionScope.Transient);
Bind<IInterface3>().To<Interface3_Impl1>().SetResolutionScope(DiResolutionScope.ScopeLifetime);
}
Property Injection and Circular References¶
The most common dependency injection type is a constructor injection, when dependency injection container creates objects and injects them into constructor of an object being resolved (this process is done recursively).
However, there are scenarios when two types reference each other. In this case constructor injection might fail. For example if type TypeA is specified as a constructor parameter in type TypeB and TypeB is specified as a constructor parameter in type TypeA, the dependency injection container will not be able to create an instance of TypeA, since it will need to create an instance of type TypeB, which requires creating an instance of type TypeA.
In such cases, property injection can be used to re-solve circular references. In this example type TypeB can be specified as a constructor parameter in type TypeA, and type TypeA can be a type of property TypeB.TypeAProperty, which will be initialized after the DI container created both types.
Here is an example of how property injection can be implemented in overridden AddServiceRegistrations() method in a sub-class of IoC.Configuration.DiContainer.ModuleAbstr:
In this example, the constructor of type CircularReferenceTestInterface2_Impl has a parameter of type ICircularReferenceTestInterface1, and the implementation of ICircularReferenceTestInterface1, CircularReferenceTestInterface1_Impl, has a setter property Property1 of type ICircularReferenceTestInterface2.
Note
The setter property used for property injection needs to be declared in implementation only.
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<ICircularReferenceTestInterface1>()
.To<CircularReferenceTestInterface1_Impl>()
.OnImplementationObjectActivated(
(diContainer, instance) =>
// Note, type of parameter 'instance' is the implementation type
// CircularReferenceTestInterface1_Impl. So we can use Property1 setter in
// CircularReferenceTestInterface1_Impl only and not in ICircularReferenceTestInterface1.
// ICircularReferenceTestInterface1 has only getter for Property1.
instance.Property1 = diContainer.Resolve<ICircularReferenceTestInterface2>())
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<ICircularReferenceTestInterface2>().To<CircularReferenceTestInterface2_Impl>()
.SetResolutionScope(DiResolutionScope.Singleton);
}
}
Type Bindings in 3-rd Party Container Modules¶
Third party module classes can be used to specify bindings.
The module class should be a sub-class or an implementation of a type returned by property Type ModuleType { get; } of IoC.Configuration.DiContainer.IDiManager object used to load the configuration.
To see of how IoC.Configuration.DiContainer.IDiManager type can be specified when loading the configuration, reference Loading from Modules (loading from modules) or Specifying DI Manager (loading from configuration file).
- Currently two implementations of IoC.Configuration.DiContainer.IDiManager are available on Nuget:
- IoC.Configuration.Autofac.AutofacDiManager available in Nuget package IoC.Configuration.Autofac
- IoC.Configuration.Autofac.NinjectDiManager available in Nuget package IoC.Configuration.Ninject
The module types are passed as parameters, when loaded the configuration from modules (see Loading from Modules), or in iocConfiguration/dependencyInjection/modules/module elements in XML configuration file, if the configuration is loaded from XML file (see Modules).
Note
If the native module has a public method void OnDiContainerReady(IDiContainer diContainer), IoC.Configuration will call this method, when the dependency injection is loaded. The native module can use the IDiContainer object to resolve types in type bindings.
Here is an example of Autofac module:
public class AutofacModule1 : AutofacModule
{
public IDiContainer DiContainer { get; private set; }
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<Interface1_Impl1>()
.As<IInterface1>()
.SingleInstance();
}
/// <summary>
/// The value of parameter <paramref name="diContainer" />
/// will be injected by <see cref="DiContainerBuilder" />.
/// </summary>
/// <param name="diContainer"></param>
public void OnDiContainerReady(IDiContainer diContainer)
{
DiContainer = diContainer;
}
}
Here is an example of Ninject module:
public class NinjectModule1 : NinjectModule
{
public IDiContainer DiContainer { get; private set; }
public override void Load()
{
Bind<IInterface1>().To<Interface1_Impl2>()
.InSingletonScope();
}
/// <summary>
/// The value of parameter <paramref name="diContainer" />
/// will be injected by <see cref="DiContainerBuilder" />.
/// </summary>
/// <param name="diContainer"></param>
public void OnDiContainerReady(IDiContainer diContainer)
{
DiContainer = diContainer;
}
}
XML Configuration File¶
An examples of XML configuration file can be found at IoCConfiguration_Overview.xml.
The sections below describe various aspects of configuration file.
Assemblies and Probing Paths¶
Elements appDataDir, plugins, additionalAssemblyProbingPaths, and assemblies define the assemblies and paths that the IoC.Configuration will search to locate the assembles.
Note
For more information about plugins refer to section Plugins.
Element: appDataDir¶
This element specifies the folder, where IoC.Configuration saves dynamically generated DLLs. The application should have write permissions to path specified in appDataDir.
Example of appDataDir in configuration file:
<appDataDir path="K:\...\IoC.Configuration.Tests\bin\TestFiles\DynamicFiles" />
Element: plugins¶
This element specifies the root folder, where plugin assemblies are, using the attribute pluginsDirPath, as well as might have plugin child elements to declare plugins (for more information about plugins refer to section Plugins).
The assemblies related to a plugin should be copied to a folder [plugins root folder]/[plugin name], where [plugins root folder] is the value of attribute pluginsDirPath of /iocConfiguration/plugins element, and [plugin name] is the value of name attribute in /iocConfiguration/plugins/plugin element.
For example the assemblies for plugin Plugin1 below should be in folder “K:...\TestDlls\PluginDlls\Plugin1”.
<plugins pluginsDirPath="K:\...\TestDlls\PluginDlls">
<!--
Plugin assemblies will be in a folder with similar name under pluginsDirPath folder.
The plugin folders will be included in assembly resolution mechanism.
-->
<!--A folder K:\...\TestDlls\PluginDlls\Plugin1 should exist. -->
<plugin name="Plugin1" />
<plugin name="Plugin2" />
<plugin name="Plugin3" enabled="false" />
</plugins>
Here is an example of file structure with plugin folders.

Element: additionalAssemblyProbingPaths¶
This element specifies additional folders that IoC.Configuration will use for assembly resolution (this includes resolving assemblies defined in element assemblies as well as re-solving assemblies, on which assemblies in assemblies elements depend).
Here is an example of additionalAssemblyProbingPaths element:
<additionalAssemblyProbingPaths>
<probingPath path="K:\...\TestDlls\ThirdPartyLibs" />
<probingPath path="K:\...\TestDlls\ContainerImplementations\Autofac" />
<probingPath path="K:\...\TestDlls\ContainerImplementations\Ninject" />
<probingPath path="K:\...\TestDlls\DynamicallyLoadedDlls" />
<probingPath path="K:\...\TestDlls\TestAssemblyResolution" />
</additionalAssemblyProbingPaths>
Element: assemblies and assembly¶
The elements assemblies and assembly specify all the assemblies that can be used when referencing types in XML configuration file. The assemblies in assemblies and their dependencies are resolved by looking up for assemblies in folders specified in elements plugins, additionalAssemblyProbingPaths, in addition to default folders (e.g., application startup folder, standard folder for .Net Core assemblies, etc).
Here is an example of assemblies element:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <assemblies>
<assembly name="TestProjects.TestForceLoadAssembly"
alias="TestForceLoadAssembly"
overrideDirectory="K:\...\TestDlls\DynamicallyLoadedDlls" />
<assembly name="OROptimizer.Shared" alias="oroptimizer_shared" />
<assembly name="IoC.Configuration" alias="ioc_config" />
<assembly name="IoC.Configuration.Autofac" alias="autofac_ext" />
<assembly name="IoC.Configuration.Ninject" alias="ninject_ext" />
<assembly name="TestProjects.Modules" alias="modules" />
<assembly name="TestProjects.DynamicallyLoadedAssembly1" alias="dynamic1" />
<assembly name="TestProjects.DynamicallyLoadedAssembly2" alias="dynamic2" />
<assembly name="TestProjects.TestPluginAssembly1" alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.ModulesForPlugin1" alias="modules_plugin1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2" alias="pluginassm2" plugin="Plugin2" />
<assembly name="TestProjects.TestPluginAssembly3" alias="pluginassm3" plugin="Plugin3" />
<assembly name="TestProjects.SharedServices" alias="shared_services" />
<assembly name="IoC.Configuration.Tests" alias="tests" />
</assemblies>
|
Attributes in assembly element¶
name: Specifies the assembly name without the file extension. Example of this attribute value is IoC.Configuration.Autofac (see the XML above).
alias: A short unique alias to use, when referencing the assembly in other elements.
Here is an example of element that references the assembly with alias dynamic1:
<services> <service type="DynamicallyLoadedAssembly1.Interfaces.IInterface1" assembly="dynamic1"> <implementation type="DynamicallyLoadedAssembly1.Implementations.Interface1_Impl1" assembly="dynamic1" scope="singleton"> </implementation> </service> </services>
plugin: An assembly that is in a plugin folder should include this attribute with value specifying the plugin name.
Here is an example of assembly TestProjects.ModulesForPlugin1 with the value of attribute plugin being Plugin1.
<assembly name="TestProjects.ModulesForPlugin1" alias="modules_plugin1" plugin="Plugin1" />
Note
There should exist some plugin element under element plugins, with the value of attribute name equal to Plugin1.
overrideDirectory: Specifies the directory, where the assembly should be loaded from. Normally this attribute should not be included in element, and the folders specified in elements plugins, additionalAssemblyProbingPaths, in addition to default folders will be searched to locate tbe assembly.
Note
Use this attribute in rare circumstances, to override the default behaviour.
Here is an example of overrideDirectory attribute usage.
<assembly name="TestProjects.TestForceLoadAssembly" alias="TestForceLoadAssembly" overrideDirectory="K:\...\TestDlls\DynamicallyLoadedDlls" />
Using Types in Configuration File¶
Many configuration elements reference C# types.
Either the full type name of the element should be specified using a type attribute (the attribute name might be different depending on element), or type alias should be specified, to reference a type declared in element under element /iocConfiguration/typeDefinitions/typeDefinitions (see below for more details).
Some examples are:
- <service type=”DynamicallyLoadedAssembly1.Interfaces.IInterface1”>
- <service type=”DynamicallyLoadedAssembly1.Interfaces.IInterface2 assembly=”shared_services”>
- <service typeRef=”IInterface1”>
- If the element uses the full type name, an optional attribute assembly can be used to specify the assembly, where the type is.
Note
Refer to Assemblies and Probing Paths for more details on assemblies in configuration file.
IoC.Configuration looks up the type in all the assemblies under element /iocConfiguration/assemblies.
Note
Refer to IoCConfiguration_GenericTypesAndTypeReUse.xml for more examples of using types in configuration file.
Generic Types in Configuration File¶
To reference generic types, list the comma separated generic type parameters within opening and closing square brackets (i.e., []) after the type name.
Some examples are:
<!--This type is similar to C# type
SharedServices.Implementations.Generic.Generic1_1<SharedServices.Implementations.Interface1_Impl1> -->
<implementation
type="SharedServices.Implementations.Generic.Generic1_1[SharedServices.Implementations.Interface1_Impl1]"
scope="singleton" />
<!--This type is similar to C# type
SharedServices.Interfaces.Generic.IGeneric2_1<SharedServices.Implementations.Generic.Generic3_1<System.Int32> -->
<service
type="SharedServices.Interfaces.Generic.IGeneric2_1[SharedServices.Implementations.Generic.Generic3_1[System.Int32]]" >
Array Types in Configuration File¶
Array types can be specified by appending character # after the array item type name.
Example is:
<!--The type definition below is similar to C# type SharedServices.Interfaces.IInterface1[]--> <service type="SharedServices.Interfaces.IInterface1#" > <!--Some implementation for service SharedServices.Interfaces.IInterface1[] goes here.--> </service>
Re-Using Types¶
To avoid specifying the full type name in multiple elements in configuration file, we can define the type in /iocConfiguration/typeDefinitions/typeDefinition element, and reference the type using tye type alias in other elements.
Here is an example of declaring a type System.Collections.Generic.IEnumerable<SharedServices.Interfaces.IInterface1> with alias IEnumerableOf_IInterface1 in typeDefinition element:
<typeDefinitions> <typeDefinition alias="IEnumerableOf_IInterface1" type="System.Collections.Generic.IEnumerable[SharedServices.Interfaces.IInterface1]" /> </typeDefinitions>
Here is an example of referencing the type with alias IEnumerableOf_IInterface1 declared in typeDefinition element:
<service typeRef="IEnumerableOf_IInterface1"> <!--Some implementation for service System.Collections.Generic.IEnumerable<SharedServices.Interfaces.IInterface1> goes here.--> </service>
Parameter Serializers¶
The element parameterSerializers is used to de-serialize textual values used for type constructor parameters and property values, into objects of specific types.
Here is an example of parameterSerializers element.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <assemblies>
<assembly name="OROptimizer.Shared" alias="oroptimizer_shared" />
<assembly name="TestProjects.TestPluginAssembly1" alias="pluginassm1" plugin="Plugin1" />
<assembly name="TestProjects.TestPluginAssembly2" alias="pluginassm1" plugin="Plugin2" />
<!--Some more assemblies here...-->
</assemblies>
<parameterSerializers
serializerAggregatorType="OROptimizer.Serializer.TypeBasedSimpleSerializerAggregator"
assembly="oroptimizer_shared">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'serializerAggregatorType' attribute
has non-default constructor.
-->
<!--<parameters>
</parameters>-->
<serializers>
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerDouble"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerLong"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerInt"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerShort"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerByte"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerBoolean"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerDateTime"
assembly="oroptimizer_shared" />
<parameterSerializer type="OROptimizer.Serializer.TypeBasedSimpleSerializerString"
assembly="oroptimizer_shared" />
<parameterSerializer type="TestPluginAssembly1.Implementations.DoorSerializer"
assembly="pluginassm1" />
<parameterSerializer type="TestPluginAssembly2.Implementations.WheelSerializer"
assembly="pluginassm2">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute has non-default constructor.
-->
<!--<parameters>
</parameters>-->
</parameterSerializer>
</serializers>
</parameterSerializers>
|
The value of attribute serializerAggregatorType in element parameterSerializers should be full name of a type that implements the interface OROptimizer.Serializer.ITypeBasedSimpleSerializerAggregator in assembly OROptimizer.Shared.dll (the assembly is available in Nuget package OROptimizer.Shared).
The default implementation of this interface is class OROptimizer.Serializer.TypeBasedSimpleSerializerAggregator in assembly OROptimizer.Shared.dll.
Attribute assembly is an assembly alias, that contains the type specified in attribute serializerAggregatorType (the assembly should be declared in some element /iocConfiguration/assemblies/assembly).
Element parameters specifies values of constructor parameters for the type specified in attribute serializerAggregatorType (for details on constructor parameters reference Constructor Parameters).
Element serializers lists the registered serializers using parameterSerializer elements. Each parameterSerializer element registers a serializer for specific type (see the Element parameterSerializer section below).
Note
Some parameter serializers are provided by default, even if we do not list them under element parameterSerializers/serializers. Examples are serializers for some common types, such as parameter serializers for System.Int32, and System.Double, which are OROptimizer.Serializer.TypeBasedSimpleSerializerInt and OROptimizer.Serializer.TypeBasedSimpleSerializerDouble.
Element parameterSerializer¶
The element parameterSerializer registers a serializer for specific type. This element has two attributes, type and assembly, which are used to specify the full type name and the assembly for a serializer class that implements interface OROptimizer.Serializer.ITypeBasedSimpleSerializer.
Here is the definition of interface OROptimizer.Serializer.ITypeBasedSimpleSerializer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | namespace OROptimizer.Serializer
{
/// <summary>
/// A simple serializer that serializes/de-serializes objects to and from strings.
/// The serialized string does not have any information about the type, so specific implementation de-serializes
/// specific type.
/// For example integer value 3 will be de-serialized from "3".
/// </summary>
public interface ITypeBasedSimpleSerializer
{
Type SerializedType { get; }
bool TryDeserialize(string valueToDeserialize, out object deserializedValue);
bool TrySerialize(object valueToSerialize, out string serializedValue);
}
}
|
Note
The property OROptimizer.Serializer.ITypeBasedSimpleSerializer.SerializedType is used to pick a deserializer type from the serializers registered in element parameterSerializers.
Example 1¶
Note
Refer to Constructor Parameters for more details on parameters element to specify constructor parameter values in configuration file.
The selfBoundService element below is a definition of self-bound service for type DynamicallyLoadedAssembly1.Implementations.SelfBoundService1 from configuration file.
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService1"
assembly="dynamic1"
scope="singleton">
<parameters>
<int32 name="param1" value="14" />
<double name="param2" value="15.3" />
<injectedObject name="param3" type="DynamicallyLoadedAssembly1.Interfaces.IInterface1"
assembly="dynamic1" />
</parameters>
</selfBoundService>
The type DynamicallyLoadedAssembly1.Implementations.SelfBoundService1 has a constructor with three parameters of types System.Int32, System.Double, and DynamicallyLoadedAssembly1.Interfaces.IInterface1.
- Since there is a parameterSerializer element (see example of parameterSerializers element above) for type System.Int32 (i.e., OROptimizer.Serializer.TypeBasedSimpleSerializerInt), which de-serializes textual values into System.Int32 values, IoC.Configuration will use OROptimizer.Serializer.TypeBasedSimpleSerializerInt to de-serialze the textual value “14” into a System.Int32 value for the constructor parameter param1.
- Since there is a parameterSerializer element (see example of parameterSerializers element above) for type System.Double (i.e., OROptimizer.Serializer.TypeBasedSimpleSerializerDouble), which de-serializes textual values into System.Double values, IoC.Configuration will use OROptimizer.Serializer.TypeBasedSimpleSerializerDouble to de-serialze the textual value “15.3” into an System.Double value for the constructor parameter param2.
- The constructor parameter param3 will be injected into constructor of DynamicallyLoadedAssembly1.Implementations.SelfBoundService1, using dependency injection mechanism, since injectedObject element is used for this parameter.
Example 2¶
Note
Refer to Constructor Parameters for more details on parameters element to specify constructor parameter values in configuration file.
The service element below defines type bindings for interface TestPluginAssembly1.Interfaces.IRoom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <service type="TestPluginAssembly1.Interfaces.IRoom" assembly="pluginassm1">
<implementation type="TestPluginAssembly1.Implementations.Room"
assembly="pluginassm1"
scope="transient">
<parameters>
<object name="door1" type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1"
value="5,185.1" />
<injectedObject name="door2" type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1" />
</parameters>
<injectedProperties>
<object name="Door2" type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1"
value="7,187.3" />
</injectedProperties>
</implementation>
</service>
|
The constructor of type TestPluginAssembly1.Implementations.Room in element implementation has two constructor parameters named door1 and door2, both of type TestPluginAssembly1.Interfaces.IDoor.
- Since there is a parameterSerializer element (see example of parameterSerializers element above) for type TestPluginAssembly1.Implementations.DoorSerializer, which de-serializes textual values into TestPluginAssembly1.Interfaces.IDoor values, IoC.Configuration will use TestPluginAssembly1.Implementations.DoorSerializer to de-serialze the textual value “5,185.1” into a TestPluginAssembly1.Interfaces.IDoor value to use for constructor parameter door1.
- The constructor parameter door2 will be injected into constructor of TestPluginAssembly1.Implementations.Room, using dependency injection mechanism, since injectedObject element is used for this parameter.
- Property TestPluginAssembly1.Implementations.Room.Door2 has a setter, and is of type TestPluginAssembly1.Interfaces.IDoor as well, therefore IoC.Configuration will use TestPluginAssembly1.Implementations.DoorSerializer as well, to de-serialze the textual value “7,187.3” into a TestPluginAssembly1.Interfaces.IDoor value and to assign this value to a property TestPluginAssembly1.Implementations.Room.Door2 in bound object of type TestPluginAssembly1.Implementations.Room.
Constructor Parameters¶
Element parameters is used to specify constructor parameter values for a type specified in XML configuration file.
Element parameters has one child element per constructor parameter.
Child elements are byte, int16, int32, int64, double, boolean, datetime, string, object, and injectedObject.
Elements, byte, int16, int32, int64, double, boolean, datetime, string, are straightforward, and are used to specify constructor parameters of the same type (byte, System.Int32, string, etc).
Element object is used to provide a constructor parameter value of arbitrary type using attributes type and assembly, as well as attribute value. The value in attribute value will be de-serialized into an instance of type specified in attributes type and assembly, using a serializer registered in element iocConfiguration/parameterSerializers for the type.
Note
Refer to Parameter Serializers for more details on parameter serializers.
Element injectedObject is used to specify a constructor parameter that should be injected using the dependency injection mechanism.
Note
Child elements injectedObject are valid based on context, where parameters element is used. For example this element can be used when specifying service bindings, as shown in examples below, however it cannot be used in settings element.
Example 1¶
In example below, service of type DynamicallyLoadedAssembly1.Implementations.SelfBoundService1 will be bound to an instance of the same type, which will be created using a constructor with three parameters of types int, double, and DynamicallyLoadedAssembly1.Interfaces.IInterface1.
- Parameter param1 of type System.Int32 will be initialized from textual value 14 using the parameter serializer OROptimizer.Serializer.TypeBasedSimpleSerializerInt in assembly OROptimizer.Shared.
- Parameter param2 of type System.Double will be initialized from textual value 15.3 using the parameter serializer OROptimizer.Serializer.TypeBasedSimpleSerializerDouble in assembly OROptimizer.Shared.
- Parameter param3 of type DynamicallyLoadedAssembly1.Interfaces.IInterface1 will be injected into constructor of DynamicallyLoadedAssembly1.Implementations.SelfBoundService1.
1 2 3 4 5 6 7 8 9 10 | <selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService1"
assembly="dynamic1"
scope="singleton">
<parameters>
<int32 name="param1" value="14" />
<double name="param2" value="15.3" />
<injectedObject name="param3" type="DynamicallyLoadedAssembly1.Interfaces.IInterface1"
assembly="dynamic1" />
</parameters>
</selfBoundService>
|
Example 2¶
In example below, service of type TestPluginAssembly1.Interfaces.IRoom will be bound to an instance of type TestPluginAssembly1.Implementations.Room, which will be created using a constructor that has two parameters, door1 and door2, of type TestPluginAssembly1.Interfaces.IDoor.
The first parameter door1 will be de-serialized from text 5,185.1, using a serializer TestPluginAssembly1.Implementations.DoorSerializer, found under element iocConfiguration/parameterSerializers for type TestPluginAssembly1.Interfaces.IDoor.
Note
Refer to Parameter Serializers for more details on parameter serializers.
The second parameter door2 will be injected into constructor of TestPluginAssembly1.Implementations.Room.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <service type="TestPluginAssembly1.Interfaces.IRoom" assembly="pluginassm1">
<implementation type="TestPluginAssembly1.Implementations.Room"
assembly="pluginassm1"
scope="transient">
<parameters>
<object name="door1" type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1"
value="5,185.1" />
<injectedObject name="door2" type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1" />
</parameters>
</implementation>
</service>
|
Example 3¶
This example is similar to Example 2 above, however parameters element is missing under the implementation type TestPluginAssembly1.Implementations.Room. Since no parameters element is provided, an instance of type TestPluginAssembly1.Implementations.Room will be injected using dependency injection mechanism, rather than using a specific constructor.
Note
If a parameters element is provided without any child parameters, an instance of type will be created using the default parameter-less constructor. Therefore the type is expected to have a default constructor. To use dependency injection mechanism to construct an instance of type, one should omit the parameters element, instead of providing an empty parameters element.
1 2 3 4 5 6 | <service type="TestPluginAssembly1.Interfaces.IRoom" assembly="pluginassm1">
<implementation type="TestPluginAssembly1.Implementations.Room"
assembly="pluginassm1"
scope="transient">
</implementation>
</service>
|
Settings¶
The configuration file has two elements related to settings: /iocConfiguration/settingsRequestor and /iocConfiguration/settings
Note
See Plugins for details on settings in plugins.
Here is an example of settings in XML configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 | <iocConfiguration>
<settingsRequestor type="SharedServices.FakeSettingsRequestor"
assembly="shared_services">
</settingsRequestor>
<settings>
<int32 name="SynchronizerFrequencyInMilliseconds" value="5000" />
<double name="MaxCharge" value="155.7" />
<string name="DisplayValue" value="Some display value" />
</settings>
</iocConfiguration>
|
Element settings lists all the settings using elements byte, int16, int32, int64, double, boolean, datetime, string, object. The values of settings are de-serialized using serializers provided in element parameterSerializers (reference section Parameter Serializers).
Element settingsRequestor is optional and if present, is used to force the user to include settings using the type specified in attributes type and assembly. The specified type should implement an interface IoC.Configuration.ISettingsRequestor, which specifies a collection of required settings that should be present in settings element.
Note
The type specified in type attribute in settingsRequestor element is fully integrated into a dependency injection framework. In other words, constructor parameters will be injected using bindings specified in dependencyInjection element.
Interface IoC.Configuration.ISettingsRequestor¶
1 2 3 4 5 6 7 8 9 10 11 12 | namespace IoC.Configuration
{
public interface ISettingsRequestor
{
/// <summary>
/// Gets the collection of settings, that should be
/// present in configuration file.
/// </summary>
[NotNull, ItemNotNull]
IEnumerable<SettingInfo> RequiredSettings { get; }
}
}
|
Accessing Setting Values in Code¶
To access the setting values in code, inject the type IoC.Configuration.ISettings as a constructor parameter, and use the methods bool GetSettingValue<T>(string name, T defaultValue, out T value) or T GetSettingValueOrThrow<T>(string name) in IoC.Configuration.ISettings.
Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class TestInjectedSettings
{
public TestInjectedSettings(ISettings settings)
{
Assert.IsTrue(settings.GetSettingValue<double>("MaxCharge", 5.3,
out var maxChargeSettingValue));
Assert.AreEqual(155.7, maxChargeSettingValue);
Assert.IsFalse(settings.GetSettingValue<int>("MaxCharge", 5,
out var settingValueNotFound_InvalidType));
Assert.AreEqual(5, settingValueNotFound_InvalidType);
Assert.IsFalse(settings.GetSettingValue<int>("MaxChargeInvalid", 7,
out var nonExistentSettingValue));
Assert.AreEqual(7, nonExistentSettingValue);
try
{
// This call will throw an exception, since there is no setting of double
// type with name "MaxChargeInvalid".
settings.GetSettingValueOrThrow<double>("MaxChargeInvalid");
Assert.Fail("An exception should have been thrown.");
}
catch
{
}
}
}
|
Note
Binding for a type TestInjectedSettings should be registered either in module class or in XML configuration file. Below is an example of registering binding for TestInjectedSettings in an IoC.Configuration module.
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr { protected override void AddServiceRegistrations() { this.Bind<TestInjectedSettings>().ToSelf(); } }
Specifying DI Manager¶
The XML configuration file has a required element diManagers, for specifying types that implement interface IoC.Configuration.DiContainer.IDiManager. The IoC.Configuration.DiContainer.IDiManager implementations are specified in child diManager elements.
Also, diManagers element has an attribute activeDiManagerName, that specifies which IoC.Configuration.DiContainer.IDiManager will be used to handle IoC type bindings and type resolutions, as well as some other dependency injection related behaviour (such as valid module types, etc).
Note
Currently two implementations of IoC.Configuration.DiContainer.IDiManager are available: IoC.Configuration.Ninject.NinjectDiManager and IoC.Configuration.Autofac.AutofacDiManager in Nuget packages IoC.Configuration.Ninject and IoC.Configuration.Autofac
The selected IoC.Configuration.DiContainer.IDiManager implementation (e.g., IoC.Configuration.Ninject.NinjectDiManager, IoC.Configuration.Autofac.AutofacDiManager) handles type bindings that are specified in IoC.Configuration modules, as well as type resolutions.
Example of this element is shown below. To switch between Ninject and Aurofac containers, one needs to set the value of activeDiManagerName to either Ninject or Aurofac.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <diManagers activeDiManagerName="Autofac">
<diManager name="Ninject"
type="IoC.Configuration.Ninject.NinjectDiManager"
assembly="ninject_ext">
<!--
Use parameters element to specify constructor parameters,
if the type specified in 'type' attribute
has non-default constructor.-->
<!--<parameters>
</parameters>-->
</diManager>
<diManager name="Autofac"
type="IoC.Configuration.Autofac.AutofacDiManager"
assembly="autofac_ext">
</diManager>
</diManagers>
|
Dependency Injection¶
The XML configuration file has dependencyInjection element which is used to specify modules (both IoC.Configuration modules, as well as native, such as Autofac or Ninject modules), service bindings, autogenerated service bindings, etc.
Modules¶
The iocConfiguration/dependencyInjection/modules element lists the modules (both IoC.Configuration modules, as well as native modules, such as Autofac or Ninject modules), that should be loaded into the IoC container. See Type Binding In Modules for more details on modules.
Here is an example of modules element in configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <iocConfiguration>
<!--...-->
<dependencyInjection>
<modules>
<!--Type Modules.Autofac.AutofacModule1 is an Autofac module and is a
subclass of Autofac.AutofacModule-->
<module type="Modules.Autofac.AutofacModule1" assembly="modules">
<parameters>
<int32 name="param1" value="1" />
</parameters>
</module>
<!--Type Modules.IoC.DiModule1 is an IoC.Configuration module and is a
subclass of IoC.Configuration.DiContainer.ModuleAbstr-->
<module type="Modules.IoC.DiModule1" assembly="modules">
<parameters>
<int32 name="param1" value="2" />
</parameters>
</module>
<!--Type Modules.Ninject.NinjectModule1 is a Ninject module and is a
subclass of Ninject.Modules.NinjectModule-->
<module type="Modules.Ninject.NinjectModule1" assembly="modules">
<parameters>
<int32 name="param1" value="3" />
</parameters>
</module>
</modules>
<!--...-->
</dependencyInjection>
<!--...-->
<iocConfiguration>
|
- Each child module element in modules element specifies a module type that should be either IoC.Configuration module (i.e., should either implement interface IoC.Configuration.DiContainer.IDiModule or be a subclass of IoC.Configuration.DiContainer.ModuleAbstr class), or should be a native module (e.g., Autofac or Ninject module).
- If the type specified by module is a native module (e.g., Autofac or Ninject module), then the type of the module should be assignable from one of the types specified by property IoC.Configuration.DiContainer.IDiManager.ModuleType in IDiManager objects listed in iocConfiguration/diManagers/diManager elements (see Specifying DI Manager for more details on specifying IoC.Configuration.DiContainer.IDiManager implementations).
- IoC.Configuration modules (i.e., modules that either implement interface IoC.Configuration.DiContainer.IDiModule or are subclasses of IoC.Configuration.DiContainer.ModuleAbstr class), and native modules (i.e., Autofac or Ninject modules), can be listed in any order in element iocConfiguration/dependencyInjection/modules.
- Constructor parameter values can be specified using parameters element, if the module does not have a default constructor (see Constructor Parameters for more details about constructor parameters).
Service Bindings¶
- The element iocConfiguration/dependencyInjection/services lists service bindings that will be loaded into IoC container.
- The element iocConfiguration/dependencyInjection/services has two types of child elements, service and selfBoundService.
Element service¶
Element service is used to bind a type specified in attributes type and assembly to one ore more types specified in implementation child elements.
Single Implementation¶
An example of service element that binds type SharedServices.Interfaces.IInterface4 in assembly with alias shared_services to a type SharedServices.Implementations.Interface4_Impl1 is shown below.
<!--...-->
<services>
<!--...-->
<service type="SharedServices.Interfaces.IInterface4" assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface4_Impl1"
assembly="shared_services"
scope="singleton">
</implementation>
</service>
<!--...-->
</services>
An instance of type SharedServices.Implementations.Interface4_Impl1 will be injected as a constructor parameter or into properties by dependency injection, when interface SharedServices.Interfaces.IInterface4 is requested.
Here is an example of injecting SharedServices.Implementations.Interface4_Impl1 as a constructor parameter interface4.
public class TestConstructorInjection
{
// An instance of type SharedServices.Implementations.Interface4_Impl1 will
// be injected for constructor parameter interface4.
public TestConstructorInjection(SharedServices.Interfaces.IInterface4 interface4)
{
}
}
Multiple Implementations¶
If multiple implementation elements are specified under service element, the type specified in element service will be bound to multiple types. In such a cases we should use System.Collections.Generic.IEnumerable<TService>.
An example of service element that binds a type SharedServices.Interfaces.IInterface8 in assembly with alias shared_services to two types, SharedServices.Implementations.Interface8_Impl1 and SharedServices.Implementations.Interface8_Impl2 is shown below.
<!--...-->
<services>
<service type="SharedServices.Interfaces.IInterface8"
assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface8_Impl1"
assembly="shared_services"
scope="singleton">
</implementation>
<implementation type="SharedServices.Implementations.Interface8_Impl2"
assembly="shared_services"
scope="transient">
</implementation>
</service>
<!--...-->
</services>
Here is an example of injecting instances of types SharedServices.Implementations.Interface8_Impl1 and SharedServices.Implementations.Interface8_Impl2 for parameter interface8Resolutions of type System.Collections.Generic.IEnumerable<SharedServices.Interfaces.IInterface8>.
In this example, the injected collection interface8Resolutions will have two items. The first item will be of type SharedServices.Implementations.Interface8_Impl1 and the second item will be of type SharedServices.Implementations.Interface8_Impl2.
public class TestConstructorInjectionForMultipleBindings
{
public TestConstructorInjection(
IEnumerable<SharedServices.Interfaces.IInterface8> interface8Resolutions)
{
}
}
Binding Scope¶
Attribute scope in element implementation under element service is used to specify binding resolution scope for resolved types (see Resolution Scopes for more details). The value of this attribute can be one of the following: singleton, transient, and scopeLifetime.
Element selfBoundService¶
Element selfBoundService is used to bind a type specified in attributes type and assembly to itself.
An example of selfBoundService element to bind type DynamicallyLoadedAssembly1.Implementations.SelfBoundService3 in assembly with alias dynamic1 to itself is shown below.
<!--...-->
<services>
<!--...-->
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService3"
assembly="dynamic1"
scope="scopeLifetime">
</selfBoundService>
<!--...-->
</services>
An instance of type DynamicallyLoadedAssembly1.Implementations.SelfBoundService3 will be injected as a constructor parameter or into properties by the dependency injection, when type DynamicallyLoadedAssembly1.Implementations.SelfBoundService3 is requested.
Here is an example of injecting DynamicallyLoadedAssembly1.Implementations.SelfBoundService3 as a constructor parameter selfBoundService3.
public class TestConstructorInjection
{
public TestConstructorInjection(
DynamicallyLoadedAssembly1.Implementations.SelfBoundService3 selfBoundService3)
{
}
}
Binding Scope¶
Attribute scope in element implementation under element service is used to specify binding resolution scope for resolved types (see Resolution Scopes for more details). The value of this attribute can be one of the following: singleton, transient, and scopeLifetime.
Element proxyService¶
Element iocConfiguration/dependencyInjection/services/proxyService (or iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/services/proxyService for plugins) can be used to resolve multiple services to the same implementation.
Lets say we have an interface IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension which extends interfaces IoC.Configuration.Tests.ProxyService.Services.IAppManager and IoC.Configuration.Tests.ProxyService.Services.IAppManager2, as shown below.
namespace IoC.Configuration.Tests.ProxyService.Services
{
public interface IAppManager_Extension : IAppManager, IAppManager2
{
IAppData DefaultApp { get; }
}
}
We want to make sure that services IoC.Configuration.Tests.ProxyService.Services.IAppManager and IoC.Configuration.Tests.ProxyService.Services.IAppManager2 are resolved to the same type, to which service IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension is resolved.
This can be done using proxyService elements as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <services>
<!--IoC.Configuration.Tests.ProxyService.Services.IAppManager
will be resolved by resolving
IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension.-->
<proxyService
type="IoC.Configuration.Tests.ProxyService.Services.IAppManager" >
<serviceToProxy
type="IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension" />
</proxyService>
<!--IoC.Configuration.Tests.ProxyService.Services.IAppManager2 will
also be resolved to
IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension.-->
<proxyService type="IoC.Configuration.Tests.ProxyService.Services.IAppManager2" >
<serviceToProxy
type="IoC.Configuration.Tests.ProxyService.Services.IAppManager_Extension"/>
</proxyService>
<!--Some more services here.-->
</services>
|
Another use case for proxy services is when have module(s) that scan assemblies and self-binds non-abstract classes. In this cases we can use “proxyService” element if we want the interface specified in “proxyService” element to resolve to exactly the same value to which the self bound class is bound.
For example lets say we have a module that has a binding like
1 | Bind<DatabaseMetadata>().ToSelf().SetResolutionScope(DiResolutionScope.Singleton);
|
If we bind IDatabaseMetadata to DatabaseMetadata in configuration like the following
1 2 3 4 5 | <services>
<service type="IDatabaseMetadata">
<implementation type="DatabaseMetadata" scope="singleton" />
</service>
<services>
|
In this case the following two resolutions will result in two different instances
1 2 3 | IDiContainer diContainer; // IDiContainer will be initialized from IoC.Configuration
var instance1 = diContainer.Resolve<DatabaseMetadata>();
var instance2 = diContainer.Resolve<IDatabaseMetadata>();
|
The reason is that the underlying native DI containers (Ninject, Autofac, etc), might disregard that there is a self bound registration for DatabaseMetadata, when registering the binding for IDatabaseMetadata. In other words, IDatabaseMetadata might be bound by using reflection to create DatabaseMetadata object, and not be bound by resolving DatabaseMetadata.
To resolve this issue, we might use ‘proxyService’ element in configuration file to bind IDatabaseMetadata interface to the same instance to which class DatabaseMetadata is bound:
1 2 3 4 5 | <services>
<proxyService type="IDatabaseMetadata">
<serviceToProxy type="DatabaseMetadata"/>
</proxyService>
<services>
|
The same result can be achieved using binding in module as follows:
1 2 3 4 5 6 7 | public class DiModule1 : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<IDatabaseMetadata>().To(x => x.Resolve<MetadataDatabaseMetadata>());
}
}
|
Element valueImplementation¶
Element valueImplementation can be used under element iocConfiguration/dependencyInjection/services/service (or iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/services/service for plugin section), to bind the service to a value specified using a value initialization element (e.g., such elements as int32, int64 collection, settingValue, classMember, object, constructedValue).
Note
Refer to Value Initialization Elements for details on value initialization elements.
Note
Refer to IoCConfiguration_valueImplementation.xml for more examples on valueImplementation element.
Example 1: Using valueImplementation to bind System.Int32 to a setting value¶
1 2 3 4 5 | <service type="System.Int32">
<valueImplementation scope="singleton">
<settingValue settingName="defaultAppId"/>
</valueImplementation>
</service>
|
Example 2: Using valueImplementation to bind System.Double to 3.5¶
1 2 3 4 5 6 7 8 9 10 | <service type="System.Double">
<valueImplementation scope="singleton">
<!--
The out of the box serializer for System.Double is
OROptimizer.Serializer.TypeBasedSimpleSerializerDouble
which is available in Nuget package OROptimizer.Shared.
-->
<object type="System.Double" value="3.5"/>
</valueImplementation>
</service>
|
Example 3: Using valueImplementation to bind service to class member¶
1 2 3 4 5 6 7 | <service type="SharedServices.Interfaces.IDbConnection">
<valueImplementation scope="transient">
<classMember
class="IoC.Configuration.Tests.ValueImplementation.Services.IDbConnectionProvider"
memberName="GetDbConnection"/>
</valueImplementation>
</service>
|
Example 4: Using valueImplementation to bind service to collection¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <service
type="System.Collections.Generic.IReadOnlyList[IoC.Configuration.Tests.ValueImplementation.Services.IAppInfo]">
<valueImplementation scope="singleton" >
<collection>
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="paramId" value="1"/>
</parameters>
</constructedValue>
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="paramId" value="2"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
|
Implementation Type Constructor Parameters¶
Normally we do not need to specify constructor parameters when specifying type bindings, since the constuctor parameters will be injected. However, in some cases we want to explicitly specify constructor parameter values in bound type.
Here are some of the cases when explicitly specifying constructor parameters might be useful:
- The bound type has multiple constructors, and we want to explicitly specify which constructor should be used.
- The bound type constructor has some parameters, which cannot be injected since no bindings are provided for the types of these parameters.
- We want to explicitly specify the constructor parameter values (say for primitive types, such as System.Int32, System.Double, etc), instead of relying on IoC container to inject these constructor parameter values.
Note
Normally, if there are multiple constructors, the IoC container will pick the constructor with largest number of parameters. This pattern is true for Autofac and Ninject, however might be different for other implementations.
Element parameters¶
- Use parameters in element implementation or selfBoundService to provide constructor parameter values.
- If parameters is used without any values (see Example 1 below), than the default constructor will be used to construct an instance of bound type, even if there are other constructors. In this case an exception will be thrown if the bound type does not have a default constructor. To let the IoC pick the constructor, do not use any parameters element in implementation and selfBoundService elements.
- IoC.Configuration will use parameter serializers specified in element iocConfiguration/parameterSerializers to de-serialize the values of parameters specified in child elements of element parameters (see Parameter Serializers).
- When the IoC.Configuration uses reflection to find the constructor using parameter types specified under parameters element. If no constructor is found, and exception will be thrown.
Example 1¶
In the example below, type DynamicallyLoadedAssembly1.Implementations.SelfBoundService1 is bound to itself.
- When injecting an instance of DynamicallyLoadedAssembly1.Implementations.SelfBoundService1, the object will be constructed using the constructor with three parameters of types System.Int32, System.Double, and DynamicallyLoadedAssembly1.Interfaces.IInterface1.
- The first and second parameter values will be de-serialized from textual values 14 and 15.3.
- The third parameter value will be injected by IoC.Configuration, since injectedObject is used for this parameter. A binding for DynamicallyLoadedAssembly1.Interfaces.IInterface1 should be specified in XML configuration file or in modules being loaded.
Note
IoC.Configuration will automatically register a self bound service for a type specified in element injectedObject, if the type is not an abstract type or an interface, and if it is not already registered in configuration file. Therefore, if in example below we replace DynamicallyLoadedAssembly1.Interfaces.IInterface1 with DynamicallyLoadedAssembly1.Interfaces.IInterface1_Implementation (i.e., non-abstract implementation of DynamicallyLoadedAssembly1.Interfaces.IInterface1), there will be no need to provide a binding for DynamicallyLoadedAssembly1.Interfaces.IInterface1_Implementation.
Note
Using injectedObject, we can specify a type other than a type registered for interface DynamicallyLoadedAssembly1.Interfaces.IInterface1 (i.e., the type of parameter param3). In other words, no matter what bindings are specified for interface DynamicallyLoadedAssembly1.Interfaces.IInterface1, the object injected for parameter param3 will be of type specified in injectedObject element.
<selfBoundService type="DynamicallyLoadedAssembly1.Implementations.SelfBoundService1"
assembly="dynamic1"
scope="singleton">
<parameters>
<int32 name="param1" value="14" />
<double name="param2" value="15.3" />
<injectedObject name="param3"
type="DynamicallyLoadedAssembly1.Interfaces.IInterface1"
assembly="dynamic1" />
</parameters>
</selfBoundService>
Example 2¶
In the example below, interface SharedServices.Interfaces.IRoom is bound to class SharedServices.Implementations.Room.
When injecting an instance of SharedServices.Interfaces.IRoom, an object of type SharedServices.Implementations.Room will be constructed using a constructor with two parameter, both of type SharedServices.Interfaces.IDoor.
- The first parameter value will be de-seriazed from string “5,185.1” provided in attribute value in element object. A parameter serializer for type SharedServices.Interfaces.IDoor should be specified in element iocConfiguration/parameterSerializers/serializers (see Parameter Serializers for more details).
- The second parameter value will be injected by IoC.Configuration, since injectedObject is used for parameter value.
Note
IoC.Configuration will automatically register a self bound service for a type specified in element injectedObject, if the type is not an abstract type or an interface, and if it is not already registered in configuration file. Therefore, no need to register a binding for type SharedServices.Interfaces.OakDoor used in injectedObject for parameter door2, since this type is non-abstract and non-interface.
Note
Using injectedObject, we can specify a type other than a type registered for interface SharedServices.Interfaces.IDoor (i.e., the type of parameter door2). In other words, no matter what bindings are specified for interface SharedServices.Interfaces.IDoor, the object injected for parameter door2 will be of type specified in injectedObject element.
<service type="SharedServices.Interfaces.IRoom" assembly="shared_services">
<implementation type="SharedServices.Implementations.Room"
assembly="shared_services"
scope="transient">
<parameters>
<object name="door1" type="SharedServices.Interfaces.IDoor"
assembly="shared_services"
value="5,185.1" />
<injectedObject name="door2" type="SharedServices.Interfaces.OakDoor"
assembly="shared_services" />
</parameters>
</implementation>
</service>
Example 3¶
In the example below, a default constructor will be used to construct an instance of SharedServices.Implementations.Interface8_Impl1, even though type SharedServices.Implementations.Interface8_Impl1 has also a non default constructor. The reason the default constructor is picked is that empty parameters element is used under element implementation.
<service type="SharedServices.Interfaces.IInterface8"
assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface8_Impl1"
assembly="shared_services"
scope="singleton">
<parameters>
</parameters>
</implementation>
</service>
In the example below, non-default constructor will be used to construct an instance of SharedServices.Implementations.Interface8_Impl1, since no parameters element is used, and the type SharedServices.Implementations.Interface8_Impl1 has both parameter-less constructor as well as constructor with parameters.
<service type="SharedServices.Interfaces.IInterface8"
assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface8_Impl1"
assembly="shared_services"
scope="singleton">
</implementation>
</service>
Property Injection¶
- IoC.Configuration allows property injection in XML configuration file (for property injection in modules see Type Bindings in IoC.Configuration Modules).
- The property value is injected using injectedProperties element under element service/implementation or selfBoundService.
- Normally we should rely on constructor injection. However property injection can be used to handle circular references, when two types reference each other.
- Property injection is done after the object is constructed. Therefore, the values of properties set by property injection will override the values set by constructor.
Example¶
In the example below interface SharedServices.Interfaces.IInterface2 is bound to type SharedServices.Implementations.Interface2_Impl3.
When type SharedServices.Interfaces.IInterface2 is injected into another type via a constructor or property injection, an instance of SharedServices.Implementations.Interface2_Impl3 will be created and its properties will be set the following way:
Property Property1 will be set to a System.Double value de-serialized from textual value 148.3.
Property Property2 will be injected by IoC.Configuration, since element injectedObject is used for this property.
Property Wheel1 will be set to an instance of SharedServices.Interfaces.IWheel de-serialized from a textual value 27,45.
Note
A parameter serializer for type SharedServices.Interfaces.IWheel should exist for type SharedServices.Interfaces.IWheel under element iocConfiguration/parameterSerializers/serializers. See Parameter Serializers for more details on how constructor and property values are de-serialized.
Note
IoC.Configuration will automatically register a self bound service for a type specified in element injectedObject, if the type is not an abstract type or an interface, and if it is not already registered in configuration file. Therefore, no need to register a binding for type SharedServices.Implementations.Interface3_Impl3 used in injectedObject for property Property2, since this type is a non-abstract and non-interface.
Note
Using injectedObject, we can specify a type other than a type registered for type of property Property2 somewhere else. By using element injectedObject we explicitly state the type of the object that should be injected, no matter what types are registered for the type of the property.
Note
The implementation type SharedServices.Implementations.Interface2_Impl3 should have a setter for property Property2, which should be assignable from type SharedServices.Implementations.Interface3_Impl3. However, the setter property is not required in interface SharedServices.Interfaces.IInterface2 specified in service element.
<service type="SharedServices.Interfaces.IInterface2" assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface2_Impl3"
assembly="shared_services"
scope="singleton">
<injectedProperties>
<double name="Property1" value="148.3" />
<injectedObject name="Property2"
type="SharedServices.Implementations.Interface3_Impl3"
assembly="shared_services" />
<object name="Wheel1"
type="SharedServices.Interfaces.IWheel"
assembly="shared_services" value="27,45" />
</injectedProperties>
</implementation>
<service>
Autogenerated Services¶
Overview¶
The XML configuration file has two elements autoService and autoServiceCustom to configure bindings for interfaces, for which the implementations are auto-generated.
Element autoService allows specifying interface implementation completely in configuration. Element autoServiceCustom allows specifying an implementation of interface IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator in child element autoServiceCodeGenerator that generates the implementation of autogenerated interface implementation.
Element autoService is easier to setup, however autoServiceCustom allows more control over the generated implementation. The motivation for adding autoServiceCustom was to provide auto-implemented interface implementations based on C# attributes applied to interfaces and interface methods and properties.
Elements autoService and autoServiceCustom can appear in any order under iocConfiguration/dependencyInjection/autoGeneratedServices and iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices elements.
Element autoService¶
Overview¶
The XML configuration file has an element autoService that can appear in any order under “iocConfiguration/dependencyInjection/autoGeneratedServices” and “iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices” elements for providing instructions to IoC.Configuration to auto-generate an implementation for an interface.
Note
Refer to IoCConfiguration_autoService.xml and tests in AutoServiceSuccessfulLoadTests.cs for more examples on autoService element.
Consider the interface IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory below, that extends IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactoryBase:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 namespace IoC.Configuration.Tests.AutoService.Services { public interface IActionValidatorFactoryBase { IReadOnlyList<IActionValidator> GetValidators(int actionTypeId, string projectGuid); } public interface IActionValidatorFactory : IActionValidatorFactoryBase { Guid PublicProjectId { get; } IActionValidator DefaultActionValidator { get; } IReadOnlyList<IActionValidator> GetValidators(ActionTypes actionType, Guid projectGuid); void SomeMethodNotInConfigFile(int param1, string param2); int SomePropertyNotInConfigFile { get; } } }We want to configure auto-generation of IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory in configuration file.
However, we are interested only in specifying the auto-generation of properties IActionValidatorFactory.DefaultActionValidator and IActionValidatorFactory.PublicProjectId, as well as in auto-generation of two overloaded methods IActionValidatorFactory.GetValidators(ActionTypes actionType, Guid projectGuid) and IActionValidatorFactoryBase.GetValidators(int actionTypeId, string projectGuid).
We can use child elements autoProperty and autoMethod to specify the implementation of methods and properties in interface IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory and its parents (i.e., in this case IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactoryBase).
IoC.Configuration will generate default implementations for methods and properties, for which no auto-implementation is configured under element autoService. For example method SomeMethodNotInConfigFile() is not configured in example below, so the generated implementation will return default(System.Int32).
Note
More details on autoProperty and autoMethod elements are provided at Element autoProperty and Element autoMethod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 <dependencyInjection> <!--Some other service bindings specified here--> <autoGeneratedServices> <autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"> <autoProperty name="DefaultActionValidator" returnType="SharedServices.Interfaces.IActionValidator"> <injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorDefault"/> </autoProperty> <autoProperty name="PublicProjectId" returnType="System.Guid" > <object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/> </autoProperty> <autoMethod name="GetValidators" returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]" reuseValue="true"> <methodSignature> <!--paramName attribute is optional, however it makes the auto-implementation more readable. --> <object paramName="actionType" typeRef="ActionTypes"/> <object paramName="projectGuid" type="System.Guid"/> </methodSignature> <if parameter1="_classMember:SharedServices.DataContracts.ActionTypes.ViewFilesList" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB"> <collection> <constructedValue type="SharedServices.Implementations.ActionValidator1"> <parameters> <int32 name="intParam" value="7"/> </parameters> </constructedValue> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> <!--Plugin1ActionValidator belongs to Plugin1. If we disable this plugin, the injectedObject element below will not be included in returned collection.--> <injectedObject type="TestPluginAssembly1.Implementations.Plugin1ActionValidator"/> </collection> </if> <if parameter1="_classMember:SharedServices.DataContracts.ActionTypes.ViewFileContents" parameter2="F981F171-B382-4F15-A8F9-FE3732918D3F"> <collection> <injectedObject type="SharedServices.Implementations.ActionValidator1" /> </collection> </if> <!--If none of conditions above are true, the default value will be returned by interface implementation.--> <default> <collection> <!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.--> <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> <injectedObject type="DynamicallyLoadedAssembly2.ActionValidator4"/> </collection> </default> </autoMethod> <!--Overloaded method GetValidators uses parameters of types System.Int32 and System.string, instead of SharedServices.DataContracts.ActionTypes and System.Guid, as in case above.--> <autoMethod name="GetValidators" returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"> <methodSignature> <!--paramName attribute is optional, however it makes the auto-implementation more readable. --> <int32 paramName="actionTypeId"/> <string paramName="projectGuid" /> </methodSignature> <!-- Attributes parameter1 and parameter2 map values of parameters param1 and param2 in GetInstances() method to returned values. --> <if parameter1="0" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB"> <collection> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> <injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator4" /> </collection> </if> <default> <collection> <!--We can also call a method or property in auto-generated interface, or in one of its base interfaces.--> <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory" memberName="DefaultActionValidator"/> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> <classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers" memberName="GetDefaultActionValidator" /> <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider" memberName="AdminLevelActionValidator"/> </collection> </default> </autoMethod> </autoService> </autoGeneratedServices> </dependencyInjection>Explanation of autoMethod for method IActionValidatorFactory.GetValidators(…) above¶
The autoMethod element above for method System.Collections.Generic.IReadOnlyList<SharedServices.Interfaces.IActionValidator> IActionValidatorFactory.GetValidators(ActionTypes actionType, Guid projectGuid) instructs IoC.Configuration to generate such an implementation that:
- If actionType==SharedServices.DataContracts.ActionTypes.ViewFilesList.ViewFilesList and projectGuid==”8663708F-C707-47E1-AEDC-2CD9291AD4CB”, then collection of three objects will be returned of the following types: SharedServices.Implementations.ActionValidator1, SharedServices.Implementations.ActionValidator3, and TestPluginAssembly1.Implementations.Plugin1ActionValidator.
- If actionType==SharedServices.DataContracts.ActionTypes.ViewFilesList.ViewFileContents and projectGuid==”F981F171-B382-4F15-A8F9-FE3732918D3F”, then collection of one object will be returned of type SharedServices.Implementations.ActionValidator1.
- For all other values of parameters, collection of three objects specified under default element will be returned.
Some notes:¶
- The service type in autoService element that is specified using attribute interface or interfaceRef should be an interface.
Note
Attribute interfaceRef is used to reference a type declared in typeDefinition element.
IoC.Configuration will setup a singleton type binding to map the interface specified in autoService element to the auto-generated implementation.
To use the autogenerated implementation, just inject the interface (in this case DynamicallyLoadedAssembly2.IActionValidatorFactory1) using constructor or property injection.
IoC.Configuration allows configuring auto-implemented properties and methods from the interface specified in autoService element, as well as from any of its parent or ancestor interfaces.
Using auto-generated implementation¶
Here is an example of using the auto-generated implementation for DynamicallyLoadedAssembly2.IActionValidatorFactory1:
public class TestActionValidatorFactory1 { public TestActionValidatorFactory1( IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory actionValidatorFactory) { var actionValidatorsList = actionValidatorFactory.GetValidators( ActionTypes.ViewFilesList, Guid.Parse("95E352DD-5C79-49D0-BD51-D62153570B61")) Assert.AreEqual(3, actionValidatorsList.Count); Assert.IsInstanceOfType(actionValidatorsList[0], typeof(SharedServices.Implementations.ActionValidator1)); Assert.IsInstanceOfType(actionValidatorsList[1], typeof(SharedServices.Implementations.ActionValidator3)); Assert.IsInstanceOfType(actionValidatorsList[2], typeof(TestPluginAssembly1.Implementations.Plugin1ActionValidator)); } }More details on configuring autoProperty and autoMethod are available at the links below:
Element autoMethod¶
Element autoMethod is used to configure the auto-generated implementation of a method in interface specified in element autoService.
An example of autoMethod elements is provided in Autogenerated Services. In this section some specifics of this element will be provided.
The format of autoMethod¶
Method name and return type in autoMethod¶
Method name is specified using the attribute name.
- Method return value type is specified using the attribute returnType and optional attribute assembly, or alternatively using attribute returnTypeRef to reference a type defined in sole /iocConfiguration/typeDefinitions/typeDefinition element.
Note
Even though we only need the method name and signature, to identify the method, the return type makes the configuration more readable. Also, the return type serves as an additional way to identify the method, if a method with similar name and signature exists in multiple extended interfaces.
The example below demonstrates how method name and return type are specified:
1 2 3 4 5 <autoMethod name="GetValidators" returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"> <!--method signature and return value elements go here...--> </autoMethod>Method signature¶
Child element methodSignature is used to specify the auto-implemented method signature.
If the method has no parameters, no methodSignature element is necessary. Otherwise, this element should be present, which should list the method parameters.
The example below demonstrates how method signature is specified:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!--autoMethod below is a configuration for a C# method System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator] GetValidators( SharedServices.DataContracts.ActionTypes actionType, System.Guid projectGuid, int someIntParam)--> <autoMethod name="GetValidators" returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"> <methodSignature> <!--paramName attribute is optional, however it makes the auto-implementation more readable. --> <object paramName="actionType" typeRef="ActionTypes"/> <object paramName="projectGuid" type="System.Guid"/> <int32 paramName="someIntParam" /> </methodSignature> <!--return value elements go here..--> </autoMethod>Specifying the return values¶
Return values are specified by using any number of optional if elements, followed by required default element.
Specifying a return value using element if
Element if is used to specify a return value by providing values for up to 10 parameters using attributes parameter1, parameter2, …, parameter10.
Attribute parameter1 corresponds to the first parameter in methodSignature element, attribute parameter2 corresponds to the second parameter in methodSignature element, and so on.
The number of parameter attributes should be the same as the number of parameters in element methodSignature.
- The method auto-implemented by IoC.Configuration will return the value specified in child element of if element, if parameters in method call are equal to the values in attributes parameter1, parameter2, etc.
Note
The child of if element should be a value initializer element, such as collection, int32, constructedValue, injectedObject, etc. Refer to Value Initialization Elements for more details on value initializer elements.
The value of parameter attribute is one of the following:
A value that will be de-serialized by a parameter serializer to a value of the parameter (example <if parameter1=”15.3”>).
Note
Refer to Parameter Serializers for more details on parameter serializers.
Example (see parameter2 with value “8663708F-C707-47E1-AEDC-2CD9291AD4CB”):
<!--The generated code will return a collection with two items of types SharedServices.Implementations.ActionValidator1 and SharedServices.Implementations.ActionValidator3 if the first parameter value is SharedServices.DataContracts.ActionTypes.ViewFilesList, and the second parameter value is a Guid "8663708F-C707-47E1-AEDC-2CD9291AD4CB" (note, this value will be serialized to System.Guid, if the parameter is of type System.Guid). --> <if parameter1="_classMember:SharedServices.DataContracts.ActionTypes.ViewFilesList" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB"> <collection> <injectedObject type="SharedServices.Implementations.ActionValidator1" /> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> </collection> </if>A class member specified by using prefix _classMember followed by class member path. Class member path is the full name of the type (or the type alias for some type defined in iocConfiguration/typeDefinitions/typeDefinition element), followed by class member name.
Note
Refer to classMember element for more details on how class members are resolved.
Note
Class member can be can be a member in the auto-generated service as well.
Example (see parameter1 with value “_classMember:ActionTypes.ViewFileContents”):
<!--The generated code will return a collection with one items of type SharedServices.Implementations.ActionValidator1, if the first parameter value is SharedServices.DataContracts.ActionTypes.ViewFileContents, and the second parameter value is a Guid "F981F171-B382-4F15-A8F9-FE3732918D3F" (note, this value will be serialized to System.Guid, if the parameter is of type System.Guid). --> <if parameter1="_classMember:ActionTypes.ViewFileContents" parameter2="F981F171-B382-4F15-A8F9-FE3732918D3F"> <collection> <injectedObject type="SharedServices.Implementations.ActionValidator1" /> </collection> </if>A setting value specified by using prefix _settings followed by a setting name. A general, or plugin setting with specified name should exist in configuration file.
Example (see parameter2 with value “_settings:Project1Guid”):
<!--The generated code will return a collection with one item of type SharedServices.Implementations.ActionValidator3, if the first parameter value is SharedServices.DataContracts.ActionTypes.ViewFileContents, and the second parameter is equal to the value of setting named **Project1Guid**. --> <if parameter1="_classMember:ActionTypes.ViewFileContents" parameter2="_settings:Project1Guid"> <collection> <injectedObject type="SharedServices.Implementations.ActionValidator3" /> </collection> </if>Specifying a return value using element default
Element default is is used to specify a value to return, if none of the conditions specified in if elements is true, or if no if element is present.
- IoC.Configuration will return the value specified in child of default element.
Note
The child of default element should be a value initializer element, such as collection, int32, constructedValue, injectedObject, etc. Refer to Value Initialization Elements for more details on value initializer elements.
Example:
<autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo"> <!--GetIntValues(): IReadOnlyList<int> GetIntValues(int param1, string param2)--> <autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" > <methodSignature> <int32 paramName="param1"/> <string paramName="param2"/> </methodSignature> <if parameter1="1" parameter2="str1"> <collection> <int32 value="17"/> </collection> </if> <default> <collection> <int32 value="18"/> <int32 value="19"/> </collection> </default> </autoMethod> <!--Some other autoMethod and autoproperty elements go here--> </autoService>Referencing the auto-implemented method parameters¶
Element parameterValue is used to reference a parameter value in auto-implemented method of auto-generated service.
This element can be used only under elements if or default under element autoMethod.
The element uses an attribute paramName to reference the parameter of auto-generated method. A parameter with this name should be declared under element ../autoService/autoMethod/methodSignature.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <autoGeneratedServices> <!--Demo of referencing auto-implemented method parameters using parameterValue element--> <autoService interface="IoC.Configuration.Tests.AutoService.Services.IAppInfoFactory"> <autoMethod name="CreateAppInfo" returnType="IoC.Configuration.Tests.AutoService.Services.IAppInfo"> <methodSignature> <int32 paramName="appId"/> <string paramName="appDescription"/> </methodSignature> <default> <constructedValue type="IoC.Configuration.Tests.AutoService.Services.AppInfo"> <parameters> <!--The value of name attribute is the name of constructor parameter in AppInfo--> <!-- The value of paramName attribute is the name of parameter in IAppInfoFactory.CreateAppInfo. This parameter should be present under autoMethod/methodSignature element. --> <!--In this example the values of name and paramName are similar, however they don't have to be.--> <parameterValue name="appId" paramName="appId" /> <parameterValue name="appDescription" paramName="appDescription" /> </parameters> </constructedValue> </default> </autoMethod> </autoService> </autoGeneratedServices>Caching the returned values¶
If constructing the object returned by the function is time consuming, an optional attribute reuseValue in element autoMethod can be used to cache the returned values.
Example:
1 2 3 4 5 6 7 8 9 <autoService interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory"> <autoMethod name="GetValidators" returnTypeRef="IEnumerableOfIResourceAccessValidator" reuseValue="true" > <!--method signature and return value elements go here...--> </autoMethod> <!--Some other autoMethod and autoProperty elements go here --> </autoService>Resolving conflicts by using declaringInterface in autoMethod¶
If the auto-implemented method with the specified name, signature, and return type is not in auto-implemented interface, but is present in multiple parent interfaces, IoC.Configuration will report an error, since it will not know which method the configuration refers to.
In such rare cases an attribute declaringInterface can be used to specify explicitly the parent interface, where the method is declared.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <!-- IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo demonstrates cases when there are multiple occurrences of auto-generated methods and properties with same signatures and return types in its base interfaces. --> <autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo"> <!--GetIntValues(): IReadOnlyList<int> GetIntValues(int param1, string param2)--> <autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" > <methodSignature> <int32 paramName="param1"/> <string paramName="param2"/> </methodSignature> <if parameter1="1" parameter2="str1"> <collection> <int32 value="17"/> </collection> </if> <default> <collection> <int32 value="18"/> <int32 value="19"/> </collection> </default> </autoMethod> <!-- This method is declared in IMemberAmbiguityDemo_Parent3, which is a base interface for IMemberAmbiguityDemo. We can provide implementation for this interface, even though it has a similar signature and return type as the method IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo.GetIntValues. By using the attribute 'declaringInterface', we make a distinction between these two. --> <autoMethod name="GetIntValues" returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent3"> <methodSignature> <int32 paramName="param1"/> <string paramName="param2"/> </methodSignature> <default> <collection> <int32 value="3"/> </collection> </default> </autoMethod> </autoService>Element autoProperty¶
Element autoProperty is used to configure the auto-generated implementation of a property in interface specified in element autoService.
An example of autoProperty elements is provided in Autogenerated Services. In this section some specifics of this element will be provided.
The Format of autoProperty¶
Property name and return type in autoProperty¶
Property name is specified using the attribute name.
- Property return value type is specified using the attribute returnType and optional attribute assembly, or alternatively using attribute returnTypeRef to reference a type defined in some /iocConfiguration/typeDefinitions/typeDefinition element.
Note
Even though we only need the property name, to identify the property, the return type makes the configuration more readable. Also, the return type serves as an additional way to identify the property, if a property with similar name exists in multiple extended interfaces.
Specifying the returned value¶
The property auto-generated by IoC.Configuration will return the value specified in child of autoProperty element.
- The child of autoProperty element should be a value initializer element, such as collection, int32, constructedValue, injectedObject, etc.
Note
Refer to Value Initialization Elements for more details on value initializer elements.
Example:¶
1 2 3 4 5 <autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"> <autoProperty name="PublicProjectId" returnType="System.Guid" > <object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/> </autoProperty> </autoService>Resolving conflicts by using declaringInterface in autoProperty¶
If the auto-implemented property with the specified name, and return type is not in auto-implemented interface, but is present in multiple parent interfaces, IoC.Configuration will report an error, since it will not know which property the configuration refers to.
In such rare cases an attribute declaringInterface can be used to specify explicitly the parent interface, where the property is declared.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <!-- IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo demonstrates cases when there are multiple occurrences of auto-generated methods and properties with same signatures and return types in base interfaces of IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo. --> <autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo"> <!-- Both IMemberAmbiguityDemo_Parent1 and IMemberAmbiguityDemo_Parent2 have properties called DefaultDbConnection with the same return types. We can auto-implement this property for each of these interfaces by using declaringInterface attribute in autoProperty element to explicitly specify the interface that own the property (declaringInterface can be used in autoMethod as well as demonstrated above) --> <!--Auto-implementation of IMemberAmbiguityDemo_Parent1.DefaultDbConnection--> <autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection" declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1"> <constructedValue type="SharedServices.Implementations.SqliteDbConnection"> <parameters> <string name="filePath" value="c:\IMemberAmbiguityDemo_Parent1_Db.sqlite"/> </parameters> </constructedValue> </autoProperty> <!--Auto-implementation of IMemberAmbiguityDemo_Parent2.DefaultDbConnection--> <autoProperty name="DefaultDbConnection" returnType="SharedServices.Interfaces.IDbConnection" declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2"> <constructedValue type="SharedServices.Implementations.SqliteDbConnection"> <parameters> <string name="filePath" value="c:\IMemberAmbiguityDemo_Parent2_Db.sqlite"/> </parameters> </constructedValue> </autoProperty> </autoService>Element autoServiceCustom¶
The XML configuration file has an element autoServiceCustom that can appear under “iocConfiguration/dependencyInjection/autoGeneratedServices” and “iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices” elements.
The autoServiceCustom element specifies the interface that needs to be auto-implemented and has a child element autoServiceCodeGenerator that specifies an implementation of interface IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator.
The implementation of interface IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator is responsible for validating the auto-generated interface and for providing a code for the auto-generating the interface implementation.
See the example below or in test project for more details.
Below is the declaration of IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator.
Click to expand IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 // Copyright (c) IoC.Configuration Project. All rights reserved. // Licensed under the MIT License. See LICENSE in the solution root for license information. using JetBrains.Annotations; using OROptimizer.DynamicCode; using OROptimizer.ServiceResolver; using System; namespace IoC.Configuration.ConfigurationFile { /// <summary> /// Generates an implementation class for interfaces specified in autoServiceCustom element in configuration file. /// </summary> public interface ICustomAutoServiceCodeGenerator { /// <summary> /// Validates the configuration of "autoServiceCustom" element. /// Throws an exception if the configuration is invalid. /// </summary> /// <param name="customAutoGeneratedServiceInfo"></param> void Validate([NotNull] ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo); /// <summary> /// Generates a C# code for the auto-implemented interface specified in "autoServiceCustom" element. /// </summary> /// <param name="customAutoGeneratedServiceInfo">Configuration of auto-implemented service configuration.</param> /// <param name="dynamicAssemblyBuilder"> /// An instance of <see cref="IDynamicAssemblyBuilder"/>. /// Use methods <see cref="IDynamicAssemblyBuilder.StartDynamicallyGeneratedClass(string, string)"/>, /// <see cref="IDynamicAssemblyBuilder.StartDynamicallyGeneratedClass(string, System.Collections.Generic.IEnumerable{string}, string)"/>, /// <see cref="IDynamicAssemblyBuilder.AddCSharpFile(string)"/>, etc., to generate the C# code for the implementation. /// </param> /// <param name="generatedClassNamespace">The generated class namespace.</param> /// <param name="generatedClassName">The generated class name without namespace.</param> void GenerateCSharp([NotNull] ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo, [NotNull] IDynamicAssemblyBuilder dynamicAssemblyBuilder, [NotNull] string generatedClassNamespace, [NotNull] string generatedClassName); /// <summary> /// Validates the configuration of "autoServiceCustom" element after the IoC container is loaded. /// Throws an exception if the configuration is invalid. /// </summary> /// <param name="diContainer">The IoC container. Use IDiContainer.<see cref="IServiceResolver.Resolve(Type)"/> to resolve types.</param> /// <param name="customAutoGeneratedServiceInfo">Information about auto-implemented interface.</param> void ValidateOnIoCContainerLoaded([NotNull] DiContainer.IDiContainer diContainer, [NotNull] ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo); } }The motivation for adding autoServiceCustom was to provide an auto-implemented interface implementation based on C# attributes applied to the interface and in interface and interface methods and properties.
For example one such scenario when autoServiceCustom might be handy is when we want to auto-implement interfaces for object relational mapping, when interfaces represent database tables, and are decorated with metadata attributes that describe the database schema.
In this case, an implementation of IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator can scan the attributes applied to an interface and interface methods and properties, and generate an implementation of an interface based on metadata attributes.
The tests in IoC.Configuration.Tests.AutoServiceCustom.AutoServiceCustomSuccessfulLoadTests.cs demonstrate an example of auto-generated repository interface implementations based on attributes applied to the interface.
Note
Refer to IoCConfiguration_autoServiceCustom.xml and tests in IoC.Configuration.Tests.AutoServiceCustom.AutoServiceCustomSuccessfulLoadTests.cs for more examples on autoServiceCustom element.
Note
This wiki uses simpler examples in IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.DemoAutoServiceCustom.cs.
Below is a simple example of setting up custom auto-service in configuration file (a segment copied from configuration file DemoIoCConfiguration_autoServiceCustom.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <dependencyInjection> <modules> </modules> <services> </services> <autoGeneratedServices> <!--Interface specified in autoServiceCustom is auto-implemented by implementation of IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository.RepositoryInterfaceImplementationGenerator that is specified in autoServiceCodeGenerator element.--> <autoServiceCustom interface="IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface1"> <autoServiceCodeGenerator> <constructedValue typeRef="DemoCustomAutoServiceCodeGenerator"> <parameters> <classMember name="connectionString" classRef="ConnectionStrings" memberName="ConnectionString1" /> </parameters> </constructedValue> </autoServiceCodeGenerator> </autoServiceCustom> <autoServiceCustom interface="IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface2"> <autoServiceCodeGenerator> <constructedValue typeRef="DemoCustomAutoServiceCodeGenerator"> <parameters> <classMember name="connectionString" classRef="ConnectionStrings" memberName="ConnectionString1" /> </parameters> </constructedValue> </autoServiceCodeGenerator> </autoServiceCustom> </autoGeneratedServices> </dependencyInjection>This configuration instructs IoC.Configuration to generate an implementation of interfaces IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface1.cs and IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface2.cs using class IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.DemoCustomAutoServiceCodeGenerator.cs specified in child element autoServiceCodeGenerator.
Below is the code in IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.DemoCustomAutoServiceCodeGenerator.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 using System; using System.IO; using System.Linq; using System.Reflection; using IoC.Configuration.ConfigurationFile; using IoC.Configuration.DiContainer; using IoC.Configuration.Tests.AutoServiceCustom.SimpleDataRepository; using NUnit.Framework; using OROptimizer; using OROptimizer.DynamicCode; using SharedServices.Interfaces; namespace IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom; /// <summary> /// This is a simple demo to demonstrate an implementation of <see cref="ICustomAutoServiceCodeGenerator"/>. /// For a better example reference <see cref="RepositoryInterfaceImplementationGenerator"/> used in tests /// in AutoServiceCustom. /// The best use of <see cref="ICustomAutoServiceCodeGenerator"/> is to generate interface implementation based /// on attributes applied to interface and interface methods (such as auto-generating entity framework interfaces based on /// table names, and column metadata attributes). /// </summary> public class DemoCustomAutoServiceCodeGenerator : ICustomAutoServiceCodeGenerator { public DemoCustomAutoServiceCodeGenerator(string connectionString) { // Demo passing parameters to ICustomAutoServiceCodeGenerator in configuration file. Assert.AreEqual(ConnectionStrings.ConnectionString1, connectionString); } /// <inheritdoc /> public void Validate(ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo) { var implementedInterfaceType = customAutoGeneratedServiceInfo.ImplementedInterface; if (!implementedInterfaceType.IsInterface || implementedInterfaceType.GetInterfaces().Length > 0 || implementedInterfaceType.GetMethods().Length != 1 || implementedInterfaceType.GetProperties().Length != 0) throw new Exception($"The demo auto-implemented interface should not have a parent interfaces and should have exactly one method."); var methodInfo = implementedInterfaceType.GetMethods().First(); if (methodInfo.GetParameters().Length != 0 || methodInfo.ReturnType != typeof(int)) throw new Exception($"The demo auto-implemented method should be veryyy simple to be short!!."); if (methodInfo.GetCustomAttributes().FirstOrDefault(x => x is SimpleMethodMetadataAttribute) == null) throw new Exception($"Method should have an attribute of type '{typeof(SimpleMethodMetadataAttribute)}'."); } /// <inheritdoc /> public void GenerateCSharp(ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo, IDynamicAssemblyBuilder dynamicAssemblyBuilder, string generatedClassNamespace, string generatedClassName) { // Use IDynamicAssemblyBuilder.AddReferencedAssembly(string assemblyPath) or // IDynamicAssemblyBuilder.AddReferencedAssembly(Type typeInAssembly) to add assemblies that will be // referenced by auto-generated assembly if types in these assemblies are used in auto-generated code. dynamicAssemblyBuilder.AddReferencedAssembly(Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll")); dynamicAssemblyBuilder.AddReferencedAssembly(typeof(IInterface1)); // By now Validate(ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo) already validated // that a single method with attribute is present in interface. var methodInfo = customAutoGeneratedServiceInfo.ImplementedInterface.GetMethods().First(); var attribute = (SimpleMethodMetadataAttribute)methodInfo.GetCustomAttributes().FirstOrDefault(x => x is SimpleMethodMetadataAttribute); var dynamicClass = dynamicAssemblyBuilder.StartDynamicallyGeneratedClass(generatedClassName, new[] { customAutoGeneratedServiceInfo.ImplementedInterface.GetTypeNameInCSharpClass() }, generatedClassNamespace); var methodData = dynamicClass.StartInterfaceImplementationMethod(methodInfo, false); methodData.AddCodeLine("{"); methodData.AddCodeLine("var testReferencedAssembly = new DynamicallyLoadedAssembly1.Dog(40);"); methodData.AddCodeLine($"return {attribute.ReturnedValue};"); methodData.AddCodeLine("}"); } /// <inheritdoc /> public void ValidateOnIoCContainerLoaded(IDiContainer diContainer, ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo) { // At this point the DI container diContainer is loaded. Do validation using some services in container // and throw an exception if necessary //diContainer.Resolve() } }Look at test class below for an example of setting up and initializing the DI container from configuration file, and resolving and using auto-generated interfaces IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface1.cs and IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface2.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 // Copyright (c) IoC.Configuration Project. All rights reserved. // Licensed under the MIT License. See LICENSE in the solution root for license information. using System.IO; using IoC.Configuration.DiContainerBuilder; using IoC.Configuration.DiContainerBuilder.FileBased; using NUnit.Framework; using OROptimizer.Utilities.Xml; using TestsSharedLibrary; namespace IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom; [TestFixture] public class DemoAutoServiceCustom { private static IContainerInfo _containerInfo; [SetUp] public static void TestSetUp() { TestsHelper.SetupLogger(); var fileBasedConfigurationParameters = new FileBasedConfigurationParameters( new FileBasedConfigurationFileContentsProvider( Path.Combine(Helpers.TestsEntryAssemblyFolder, @"DocumentationTests\AutoServiceCustom\DemoIoCConfiguration_autoServiceCustom.xml")), Helpers.TestsEntryAssemblyFolder, // LoadedAssembliesForTests is an implementation of ILoadedAssemblies that has a method // "IEnumerable<Assembly> GetAssemblies()" that returns list of assemblies to add as references to // generate dynamic assembly. new LoadedAssembliesForTests()) { AdditionalReferencedAssemblies = new [] { // List additional assemblies that should be added to dynamically generated assembly as references Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"), Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly2.dll") }, AttributeValueTransformers = new[] {new FileFolderPathAttributeValueTransformer()}, ConfigurationFileXmlDocumentLoaded = (sender, e) => Helpers.EnsureConfigurationDirectoryExistsOrThrow(e.XmlDocument.SelectElement("/iocConfiguration/appDataDir").GetAttribute("path")) }; _containerInfo = new DiContainerBuilder.DiContainerBuilder() .StartFileBasedDi(fileBasedConfigurationParameters, out _) .WithoutPresetDiContainer() .RegisterModules().Start(); } [Test] public void Demo() { var simpleAutoImplementedInterface1 = _containerInfo.DiContainer.Resolve<ISimpleAutoImplementedInterface1>(); Assert.AreEqual(10, simpleAutoImplementedInterface1.GetValue()); var simpleAutoImplementedInterface2 = _containerInfo.DiContainer.Resolve<ISimpleAutoImplementedInterface2>(); Assert.AreEqual(20, simpleAutoImplementedInterface2.GetSomeOtherValue()); } [TearDown] public static void TestTeaDown() { _containerInfo.Dispose(); } }
Value Initialization Elements¶
Value initialization elements are elements that are used to specify values in different contexts. Some examples are using elements like int32, constructedValue, injectedObject, object, or constructedValue to specify constructor parameter value, or a value to returned in autoMethod or autoProperty elements.
Value initialization elements normally have attributes or child elements to specify the value, and might have some additional attributes, based on the type of the element and the context, where the element is used.
For example, if the value initialization element is used to specify injected property or constructor parameter value, the element should have a name attribute, to specify the constructor parameter or property name.
On the other hand, if the element is used to specify a returned value in autoMethod or autoProperty element, no name attribute should be present.
Predefined Type Value Initializer Elements¶
Predefined type value elements are elements used to provide values for some predefined types, such as System.Int32, System.Double, System.DateTime, etc.
These elements have a name, that reflects the type of the value being specified (e.g., <int32>, <datetime>, etc).
The value specified in value attribute in these elements is serialized/deserialized using one of the classes in package OROptimizer.Shared, that implement OROptimizer.Serializer.ITypeBasedSimpleSerializer.
Note
Refer to Parameter Serializers for more details on parameter serializers.
For example the value specified in element datetime is serialized using serialized/deserialized using the class OROptimizer.Serializer.TypeBasedSimpleSerializerDateTime.
The serializers used to serialize/deserialize the value in value element can be replaced, by specifying a different serializer in element iocConfiguration/parameterSerializers/serializers/parameterSerializer (see Parameter Serializers).
Note
To see the serializers loaded by IoC.Configuration for different types, run the IoC.Configuration with logging level set to INFO.
The following is the overview of predefined value initialization elements:
- byte: Used to specify values of type System.Byte.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerByte.
- int16: Used to specify values of type System.Int16.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerShort.
- int32: Used to specify values of type System.Int32.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerInt.
- int64: Used to specify values of type System.Int64.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerLong.
- double: Used to specify values of type System.Double.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerDouble.
- datetime: Used to specify values of type System.DateTime.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerLong.
- boolean: Used to specify values of type System.Boolean.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerBoolean.
- string: Used to specify values of type System.String.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerString.
- datetime: Used to specify values of type System.DateTime.
- The serializer class is OROptimizer.Serializer.TypeBasedSimpleSerializerLong.
Example 1: Using double and datetime elements as service implementation constructor parameters¶
1 2 3 4 5 6 7 8 9 10 11 12 | <service type="SharedServices.Interfaces.IInterface2" >
<!--Test constructor parameters-->
<implementation type="SharedServices.Implementations.Interface2_Impl1"
scope="singleton">
<parameters>
<datetime name="param1" value="2014-10-29 23:59:59.099" />
<double name="param2" value="125.1" />
<injectedObject name="param3"
type="SharedServices.Interfaces.IInterface3" />
</parameters>
</implementation>
</service>
|
Example 2: Using int32 element to specify a return value in autoProperty element¶
1 2 3 4 5 | <autoService interfaceRef="IProjectIds" >
<autoProperty name="DefaultProjectId" returnType="System.Int32">
<int32 value="1"/>
</autoProperty>
</autoService>
|
Example 2: int32, double, and string elements in settings element¶
1 2 3 4 5 | <settings>
<int32 name="SynchronizerFrequencyInMilliseconds" value="5000" />
<double name="MaxCharge" value="155.7" />
<string name="DisplayValue" value="Some display value" />
</settings>
|
object element¶
Element object is used to specify a value by using value attribute, that is de-serialize by a serializer specified in iocConfiguration/parameterSerializers/serializers/parameterSerializer elements.
Note
Refer to Parameter Serializers for more details on parameter serializers.
Note
- IoC.Configuration provides default parameter serializers for some types. The types for which parameter serializers are provided out of the box are:
- System.Byte, System.Int16, System.Int32, System.Int64, System.Double, System.Boolean, System.DateTime, System.String, and System.Guid.
Example 1: Using object element in settings element¶
1 2 3 4 5 6 | <settings>
<object name="Project1Guid" typeRef="Guid"
value="EA91B230-3FF8-43FA-978B-3261493D58A3" />
<object name="Project2Guid" typeRef="Guid"
value="9EDC7F1A-6BD6-4277-9015-5A9277218681" />
</settings>
|
Example 2: Using object element to specify a returned value in autoProperty and autoMethod elements¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <autoGeneratedServices>
<autoService interfaceRef="IProjectGuids" >
<autoProperty name="Project1" returnTypeRef="Guid">
<object typeRef="Guid"
value="966FE6A6-76AC-4895-84B2-47E27E58FD02"/>
</autoProperty>
<autoMethod name="GetDefaultProject"
returnTypeRef="Guid">
<default>
<object typeRef="Guid"
value="1E08071B-D02C-4830-AE3C-C9E78A29EA37"/>
</default>
</autoMethod>
</autoService>
<autoGeneratedServices>
|
Example 3: Using object element to specify constructor and injected property values for service implementation¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <service type="TestPluginAssembly1.Interfaces.IRoom">
<implementation type="TestPluginAssembly1.Implementations.Room" scope="transient">
<parameters>
<object name="door1" type="TestPluginAssembly1.Interfaces.IDoor"
value="5,185.1" />
<injectedObject name="door2"
type="TestPluginAssembly1.Interfaces.IDoor" />
</parameters>
<injectedProperties>
<object name="Door2"
type="TestPluginAssembly1.Interfaces.IDoor"
value="7,187.3" />
</injectedProperties>
</implementation>
</service>
|
injectedObject element¶
Element injectedObject can be used to specify a value that will be injected by IoC.Configuration.
The type to inject is specified using either type attribute (and optional assembly attribute), or typeRef attribute.
If the type to inject is non-abstract and non-interface, and has a public constructor, IoC.Configuration will create a binding for the type.
Otherwise, a binding for the type should be specified either in configuration file, or in one of the loaded IoC modules.
Example 1: Using injectedObject element to specify service implementation constructor parameter value¶
1 2 3 4 5 6 7 8 9 10 11 | <service type="SharedServices.Interfaces.IInterface2" >
<implementation type="SharedServices.Implementations.Interface2_Impl1"
scope="singleton">
<parameters>
<datetime name="param1" value="2014-10-29 23:59:59.099" />
<double name="param2" value="125.1" />
<injectedObject name="param3"
type="SharedServices.Interfaces.IInterface3" />
</parameters>
</implementation>
</service>
|
Example 2: Using injectedObject element to specify injected property value in service implementation¶
1 2 3 4 5 6 7 8 9 10 11 12 | <service type="SharedServices.Interfaces.IInterface2" >
<implementation type="SharedServices.Implementations.Interface2_Impl2"
scope="singleton">
<injectedProperties>
<datetime name="Property1"
value="1915-04-24 00:00:00.001" />
<double name="Property2" value="365.41" />
<injectedObject name="Property3"
type="SharedServices.Interfaces.IInterface3" />
</injectedProperties>
</implementation>
</service>
|
Example 2: Using injectedObject element to specify a returned value in autoProperty element¶
1 2 3 4 5 6 7 | <autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
<autoProperty name="DefaultActionValidator"
returnType="SharedServices.Interfaces.IActionValidator">
<injectedObject
type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorDefault"/>
</autoProperty>
</autoService>
|
collection element¶
Collection element is used to specify collection values.
Based on the context, in which collection element is used, it might use collectionType and itemType attributes to specify collection type and collection items type, or these values will be derived by IoC.Configuration.
Note
The possible values of collectionType attribute currently are enumerable, list, readOnlyList, and array.
For example, if collection is used to specified as a constructor parameter, or injected property value, collectionType and itemType attributes are required, along with the name attribute.
On the other hand, if collection is used to provide a return value in autoProperty or autoMethod elements, this attributes are not used, and IoC.Configuration determines the type of the collection from the auto-generated property or method return type.
Note
Refer to IoCConfiguration_collection.xml for more examples on collection element.
Example 1: Using collection element to specify constructed parameter value in service implementation¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <services>
<selfBoundService
type="IoC.Configuration.Tests.Collection.Services.CollectionsTestClass1"
scope="singleton" >
<parameters>
<!--Demo of collection element used as a constructor parameter.-->
<collection name="readOnlyListParam"
collectionType="readOnlyList"
itemType="System.Int32">
<int32 value="17"/>
<int32 value="24"/>
<int32 value="27"/>
</collection>
<!--Demo of collection element used as a constructor parameter.-->
<collection name="arrayParam"
collectionType="array"
itemTypeRef="IInterface1">
<injectedObject typeRef="IInterface1"/>
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="29"/>
</parameters>
</constructedValue>
</collection>
</parameters>
</selfBoundService>
<services>
|
Example 2: Using collection element to specify injected property value¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <services>
<selfBoundService
type="IoC.Configuration.Tests.Collection.Services.CollectionsTestClass1"
scope="singleton" >
<injectedProperties>
<!--Demo of collection element used to initialize
the value of injected property.-->
<collection name="EnumerableValues"
collectionType="enumerable"
itemType="SharedServices.Interfaces.IInterface1" >
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="18"/>
</parameters>
</constructedValue>
<settingValue settingName="DefaultInterface1Value"/>
<injectedObject typeRef="IInterface1"/>
</collection>
<!--Demo of collection element used to initialize
the value of injected property.-->
<collection name="ListValues"
collectionType="list"
itemTypeRef="IInterface1">
<injectedObject typeRef="IInterface1"/>
<settingValue settingName="DefaultInterface1Value"/>
<constructedValue typeRef="Interface1_Impl">
<parameters>
<int32 name="param1" value="139"/>
</parameters>
</constructedValue>
</collection>
</injectedProperties>
</selfBoundService>
<services>
|
Example 3: Using collection element to specify a returned value for auto-generated method¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <autoGeneratedServices>
<!--Demo of collection element used in auto-implemented method and property
return values.-->
<autoService interface="IoC.Configuration.Tests.Collection.Services.IAutoService1">
<autoMethod name="GetAllActionIds"
returnType="System.Collections.Generic.IReadOnlyList[System.Int32]">
<methodSignature>
<int32 paramName="appId"/>
</methodSignature>
<if parameter1="3">
<collection>
<int32 value="27"/>
<int32 value="17"/>
</collection>
</if>
<default>
<collection>
<int32 value="13"/>
<int32 value="27"/>
<int32 value="17"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
|
Example 4: Using collection element to provide a service implementation¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <service type="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IDbConnection]">
<valueImplementation scope="singleton">
<collection>
<settingValue settingName="DefaultDBConnection"/>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2012"/>
<string name="databaseName" value="DB1"/>
<string name="userName" value="user1"/>
<string name="password" value="password123"/>
</parameters>
</constructedValue>
<constructedValue type="SharedServices.Implementations.SqlServerDbConnection">
<parameters>
<string name="serverName" value="SQLSERVER2016"/>
<string name="databaseName" value="DB2"/>
<string name="userName" value="user2"/>
<string name="password" value="password456"/>
</parameters>
</constructedValue>
<constructedValue type="TestPluginAssembly1.Implementations.MySqlDbConnection">
<parameters>
<string name="connectionString" value="user=User1;password=123"/>
</parameters>
</constructedValue>
</collection>
</valueImplementation>
</service>
|
constructedValue element¶
The constructedValue element is used to construct a value in configuration file.
The constructedValue element can be used recursively in another constructedValue to specify the constructor parameter or injected property values.
Note
Refer to IoCConfiguration_constructedValue.xml for more examples on constructedValue element.
Below are some examples of using constructedValue element.
Example 1: Using constructedValue element to define a setting of type IoC.Configuration.Tests.ConstructedValue.Services.AppInfo¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <settings>
<object name="App1" typeRef="IAppInfo" value="1, App 1"/>
<!--AppInfo is declared in element typeDefinitions, and references a type
IoC.Configuration.Tests.ConstructedValue.Services.AppInfo. -->
<constructedValue name="App2" typeRef="AppInfo" >
<parameters>
<int32 name="Id" value="2"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 2"/>
</injectedProperties>
</constructedValue>
</settings>
|
Example 2: Using constructedValue element to define a service implementation¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <services>
<service typeRef="IAppInfo">
<valueImplementation scope="singleton">
<!--Demo of constructedValue to provide an implementation
for a service under valueImplementation element.-->
<constructedValue typeRef="AppInfo">
<parameters>
<int32 name="id" value="8"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 8"/>
</injectedProperties>
</constructedValue>
</valueImplementation>
</service>
</services>
|
Example 3: Using constructedValue element to specify a value returned in autoProperty element¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <autoGeneratedServices>
<autoService interface="IoC.Configuration.Tests.ConstructedValue.Services.IAppInfoFactory">
<autoProperty name="DefaultAppInfo" returnTypeRef="IAppInfo">
<constructedValue typeRef="AppInfo" >
<parameters>
<int32 name="id" value="11"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 11"/>
</injectedProperties>
</constructedValue>
</autoProperty>
</autoService>
</autoGeneratedServices>
|
Example 4: Using constructedValue element to specify a value returned in autoMethod element¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <autoGeneratedServices>
<autoService interface="IoC.Configuration.Tests.ConstructedValue.Services.IAppInfoFactory">
<autoMethod name="CreateAppInfo" returnTypeRef="IAppInfo">
<default>
<constructedValue typeRef="AppInfo" >
<parameters>
<int32 name="id" value="12"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 12"/>
</injectedProperties>
</constructedValue>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
|
Example 5: Using constructedValue element as a parameter value in another constructedValue element¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <settings>
<constructedValue
name="DecoratedAppInfo"
type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfoDecorator">
<parameters>
<constructedValue
name="appInfo"
type="IoC.Configuration.Tests.ConstructedValue.Services.AppInfoDecorator">
<parameters>
<constructedValue name="appInfo" typeRef="AppInfo">
<parameters>
<int32 name="id" value="25"/>
</parameters>
<injectedProperties>
<string name="Description" value="App 25"/>
</injectedProperties>
</constructedValue>
</parameters>
</constructedValue>
</parameters>
</constructedValue>
</settings>
|
settingValue element¶
The settingValue allows referencing a setting value in configuration file.
Note
For more details on settings see Settings.
Note
Refer to IoCConfiguration_settingValue_ReferencingInConfiguration.xml for more examples on settingValue element.
Example 1: Using settingValue element to provide a service implementation¶
1 2 3 4 5 6 | <service type="System.Int32">
<valueImplementation scope="transient">
<!--Demo of using a setting value in valueImplementation.-->
<settingValue settingName="defaultInt"/>
</valueImplementation>
</service>
|
Example 2: Using settingValue element in collection element¶
1 2 3 4 5 6 7 8 9 10 | <service type="System.Collections.Generic.IReadOnlyList[System.Int32]">
<valueImplementation scope="singleton">
<collection>
<!--Example of using setting value in collection element-->
<settingValue settingName="defaultInt"/>
<settingValue settingName="app1"/>
<int32 value="78"/>
</collection>
</valueImplementation>
</service>
|
Example 3: Using settingValue element to specify constructor parameter and injected property values¶
1 2 3 4 5 6 7 8 9 10 11 12 | <service type="IoC.Configuration.Tests.SettingValue.Services.IAppInfo" >
<implementation type="IoC.Configuration.Tests.SettingValue.Services.AppInfo" scope="transient">
<parameters>
<!--Demo of using settingValue to inject value into an implementation constructor.-->
<settingValue name="appId" settingName="defaultAppId"/>
</parameters>
<injectedProperties>
<!--Demo of using settingValue to inject value into an implementation property.-->
<settingValue name="AppDescription" settingName="defaultAppDescr"/>
</injectedProperties>
</implementation>
</service>
|
Example 4: Referencing setting values in autoMethod and autoProperty elements¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <autoGeneratedServices>
<autoService interface="IoC.Configuration.Tests.SettingValue.Services.IAppIds">
<autoMethod name="GetAppIds"
returnType="System.Collections.Generic.IReadOnlyList[System.Int32]">
<methodSignature>
<string paramName="platformType"/>
</methodSignature>
<!--Demo of using the value of setting named "android" in if condition
in autoMethod-->
<if parameter1="_settings:android">
<collection>
<!--Demo of setting value used as one of returned values in
autoMethod if element.-->
<settingValue settingName="defaultAppId"/>
<settingValue settingName="app1"/>
<int32 value="9"/>
</collection>
</if>
<default>
<collection>
<!--Demo of setting value used as one of returned values in
autoMethod default element.-->
<settingValue settingName="defaultAppId"/>
<int32 value="8"/>
</collection>
</default>
</autoMethod>
<autoProperty name="MainAppId" returnType="System.Int32">
<!--Demo of setting value used as return value of autoProperty element.-->
<settingValue settingName="defaultAppId"/>
</autoProperty>
</autoService>
</autoGeneratedServices>
|
Example 5: Referencing setting value in if element under autoMethod element¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"
reuseValue="true">
<methodSignature>
<object paramName="actionType" typeRef="ActionTypes"/>
<object paramName="projectGuid" type="System.Guid"/>
</methodSignature>
<!--Use _classMember: prefix in if elements to reference class member in if
condition in auto-implemented method.-->
<if parameter1="_classMember:ActionTypes.ViewFileContents" parameter2="_settings:Project1Guid">
<collection>
<injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator1" />
</collection>
</if>
<default>
<collection>
<injectedObject type="SharedServices.Implementations.ActionValidator3" />
<injectedObject type="DynamicallyLoadedAssembly2.ActionValidator4"/>
</collection>
</default>
</autoMethod>
<autoService>
|
classMember element¶
The classMember element is used to reference class member values (i.e., class variables, constant values, properties, method call results) in configuration file.
This element uses attribute class (and optional attribute assembly), or alternatively, an attribute classRef to specify the class, as well as attribute memberName, to specify the class member name.
The element classMember can be used to reference enum values as well. Example: <classMember class=”SharedServices.DataContracts.ActionTypes” memberName=”ViewFilesList” />.
Referencing non-static and non-constant class members¶
If the class member is non-static, and non-constant, IoC.Configuration will get the class member value by first resolving the class instance from the dependency injection container.
If the class is non-interface, non-abstract, and has a public constructor, IoC.Configuration will generate a self-binding for the class.
Otherwise, a binding should be provided either in configuration file, or in one of dependency injection modules.
Note
Refer to IoCConfiguration_classMember.xml for more examples on classMember element.
Example 1: Using classMember to provide a service implementation¶
1 2 3 4 5 6 7 8 9 10 11 | <service type="System.Int32">
<valueImplementation scope="singleton">
<!--Example of classMember in valueImplementation.
Since IAppIds.DefaultAppId is non-static,
IAppIds will be resolved from dependency injection container, and the
value of property DefaultAppId of resolved object will be bound
to System.Int32
-->
<classMember classRef="IAppIds" memberName="DefaultAppId" />
</valueImplementation>
</service>
|
Example 2: Using classMember in collection element¶
1 2 3 4 5 6 7 8 9 | <service type="System.Collections.Generic.IReadOnlyList[System.Int32]" >
<valueImplementation scope="singleton">
<collection>
<!--Demo of classMember in collection element.-->
<classMember classRef="ConstAndStaticAppIds" memberName="AppId1"/>
<classMember classRef="IAppIds" memberName="DefaultAppId"/>
</collection>
</valueImplementation>
</service>
|
Example 3: Using classMember to specify a returned value in autoProperty element¶
1 2 3 4 5 6 7 8 9 | <autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interfaceRef="IAppIds">
<autoProperty name="DefaultAppId" returnType="System.Int32">
<!--Example of using classMember attribute in auto property.-->
<classMember class="System.Int32" memberName="MaxValue"/>
</autoProperty>
</autoService>
|
Example 3: Referencing class member in if element under autoMethod element¶
To reference class members in if element attributes in autoMethod, use _classMember: prefix followed by class full name (or type alias name, for a type declared in typeDefinition element), period, and the class member name.
Note
Refer to Autogenerated Services and Element autoMethod for more details on autoMethod element.
In the example below, we reference a class member IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId (it is assumed that the configuration has a typeDefinition element for a type IoC.Configuration.Tests.ClassMember.Services.IAppIds, that has an alias IAppIds)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <autoService interface="IoC.Configuration.Tests.ClassMember.Services.IAppIdToPriority">
<autoMethod name="GetPriority" returnType="System.Int32">
<methodSignature>
<int32 paramName="appId"/>
</methodSignature>
<!--Property IoC.Configuration.Tests.ClassMember.Services.IAppIds.DefaultAppId
is non-static, therefore IoC.Configuration.Tests.ClassMember.Services.IAppIds
will be resolved from dependency injection container, and the value of property
DefaultAppId in resolved object will be used in if condition-->
<if parameter1="_classMember:IAppIds.DefaultAppId">
<int32 value="14" />
</if>
<default>
<int32 value="1"/>
</default>
</autoMethod>
</autoService>
|
Example 3: Using classMember to call methods with parameters¶
If the class member is a method, we can use parameters child element to specify parameter values when the method is called.
See the usage of classMember elements in the example below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <autoService interface="IoC.Configuration.Tests.ClassMember.Services.IAppInfos">
<autoProperty name="AllAppInfos"
returnType="System.Collections.Generic.IReadOnlyList[....Services.IAppInfo]" >
<collection>
<!--
An example of calling a non static factory method to create an instance of
IAppInfo. Since method IAppInfoFactory.CreateAppInfo(appId, appDescription)
is non-static, an instance of IAppInfoFactory will be resolved using the DI
container.
Also, since IAppInfoFactory is an interface, a binding for IAppInfoFactory
should be configured in configuration file or in some module.
-->
<classMember class="...Tests.ClassMember.Services.IAppInfoFactory"
memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1258"/>
<string name="appDescription"
value="App info created with non-static method call."/>
</parameters>
</classMember>
<!--
An example of calling a static factory method to create an instance
of IAppInfo.
-->
<classMember class="....Tests.ClassMember.Services.StaticAppInfoFactory"
memberName="CreateAppInfo">
<parameters>
<int32 name="appId" value="1259"/>
<string name="appDescription"
value="App info created with static method call."/>
</parameters>
</classMember>
</collection>
</autoProperty>
</autoService>
|
parameterValue element¶
Element parameterValue is used to reference a parameter value in auto-implemented method of auto-generated service.
This element can be used only under elements if or default under element autoMethod.
Note
Refer to Autogenerated Services for more details on auto-generated services.
The element uses an attribute paramName to reference the parameter of auto-generated method. A parameter with this name should be declared under element ../autoService/autoMethod/methodSignature.
An example below demonstrated an example of using an element parameterValue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <autoGeneratedServices>
<!--Demo of referencing auto-implemented method parameters using
parameterValue element-->
<autoService
interface="IoC.Configuration.Tests.AutoService.Services.IAppInfoFactory">
<autoMethod name="CreateAppInfo"
returnType="IoC.Configuration.Tests.AutoService.Services.IAppInfo">
<methodSignature>
<int32 paramName="appId"/>
<string paramName="appDescription"/>
</methodSignature>
<default>
<constructedValue
type="IoC.Configuration.Tests.AutoService.Services.AppInfo">
<parameters>
<!--The value of name attribute is the name of constructor parameter
in AppInfo-->
<!--
The value of paramName attribute is the name of parameter in
IAppInfoFactory.CreateAppInfo.
This parameter should be present under autoMethod/methodSignature element.
-->
<!--In this example the values of name and paramName are similar, however
they don't have to be.-->
<parameterValue name="appId" paramName="appId" />
<parameterValue name="appDescription" paramName="appDescription" />
</parameters>
</constructedValue>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
|
Startup Actions¶
The XML Configuration file has iocConfiguration/startupActions/startupAction elements for specifying any number of startup actions. Each startupAction element specifies a type that is an implementation of interface IoC.Configuration.OnApplicationStart.IStartupAction.
When the XML configuration file is loaded IoC.Configuration will call the method IoC.Configuration.OnApplicationStart.IStartupAction.Start() for each startup action specified in startupAction elements.
When the XML configuration file is disposed of (when IoC.Configuration.DiContainerBuilder.IContainerInfo is disposed of), IoC.Configuration.OnApplicationStart.IStartupAction.Stop() is called on each startup action.
Startup actions are integrated into dependency injection mechanism. Therefore, the constructor parameters of IoC.Configuration.OnApplicationStart.IStartupAction implementations specified in startupAction elements will be injected using the bindings specified in XML Configuration file or in modules referenced by the configuration file. Also, parameters and injectedProperties elements can used with startupActions to specify constructor parameter values or to inject properties.
IoC.Configuration waits for up to 15 seconds, to make sure that all startup actions are given enough time to properly stop (e.g., stop the threads if necessary).
Note
If all startup actions have true value of property IStartupAction.ActionExecutionCompleted, before 15 seconds passes, the wait time will be shorter.
Here is an example of startup action elements in configuration file:
<startupActions>
<startupAction type="DynamicallyLoadedAssembly1.Implementations.StartupAction1"
assembly="dynamic1">
<!--Use parameters element to specify constructor parameters if necessary.-->
<!--<parameters></parameters>-->
<!--Use injectedProperties element to inject properties into startup action if necessary.-->
<!--<injectedProperties></injectedProperties>-->
</startupAction>
<startupAction type="DynamicallyLoadedAssembly1.Implementations.StartupAction2"
assembly="dynamic1"></startupAction>
</startupActions>
Here is the definition of interface IoC.Configuration.OnApplicationStart.IStartupAction
public interface IStartupAction
{
/// <summary>
/// If <c>true</c>, the action was successfully stopped.
/// </summary>
bool ActionExecutionCompleted { get; }
/// <summary>
/// Starts the action.
/// </summary>
void Start();
/// <summary>
/// Stops the action.
/// </summary>
void Stop();
}
Plugins¶
XML Configuration file has elements to specify plugins. Plugins are extensions that allow specifying additional type bindings, plugin specific settings and some other functionality:
Adding a Plugin¶
To add a plugin do the following:
Add a child element plugin to iocConfiguration/plugins and specify the plugin name using the name attribute. See the example below:
Note
All the types related to plugins should be in assemblies that are in a directory [plugins directoy][plugin name], where [plugins directoy] is the directory specified in attribute pluginsDirPath of element iocConfiguration/plugins and [plugin name] is the value of attribute name of element iocConfiguration/plugins/plugin.
<plugins pluginsDirPath="K:\...\TestDlls\PluginDlls"> <!-- Plugin assemblies will be in a folder with similar name under pluginsDirPath folder. The plugin folders will be included in assembly resolution mechanism. --> <!--A folder K:\...\TestDlls\PluginDlls\Plugin1 should exist. --> <plugin name="Plugin1" /> <plugin name="Plugin2" /> <plugin name="Plugin3" enabled="false" /> </plugins>
Add a child element pluginSetup to iocConfiguration/pluginsSetup (iocConfiguration/pluginsSetup is next to iocConfiguration/startupActions element), and make sure to use the same value for plugin attribute as the value of attribute name in plugin element mentioned in step 1).
- Here is an example of iocConfiguration/pluginsSetup/pluginSetup element with explanation of some elements in pluginSetup element.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | <pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--The type in pluginImplementation should be non-abstract class
that implements IoC.Configuration.IPlugin and which has a public constructor-->
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1">
<parameters>
<int64 name="param1" value="25" />
</parameters>
<injectedProperties>
<int64 name="Property2" value="35"/>
</injectedProperties>
</pluginImplementation>
<settings>
<int32 name="Int32Setting1" value="25" />
<int64 name="Int64Setting1" value="38" />
<string name="StringSetting1" value="String Value 1" />
</settings>
<webApi>
<controllerAssemblies>
<!--
Specify assemblies with API controllers.
The user of IoC.Configuration should add the assemblies to MVC using
IMvcBuilder.AddApplicationPart(System.Reflection.Assembly)
-->
<controllerAssembly assembly="pluginassm1" />
<controllerAssembly assembly="plugin1api" />
</controllerAssemblies>
</webApi>
<dependencyInjection>
<modules>
<module type="ModulesForPlugin1.Ninject.NinjectModule1">
<parameters>
<int32 name="param1" value="101" />
</parameters>
</module>
<module type="ModulesForPlugin1.Autofac.AutofacModule1">
<parameters>
<int32 name="param1" value="102" />
</parameters>
</module>
<module type="ModulesForPlugin1.IoC.DiModule1">
<parameters>
<int32 name="param1" value="103" />
</parameters>
</module>
</modules>
<services>
<service type="TestPluginAssembly1.Interfaces.IDoor">
<implementation type="TestPluginAssembly1.Implementations.Door"
scope="transient">
<parameters>
<int32 name="Color" value="3" />
<double name="Height" value="180" />
</parameters>
</implementation>
</service>
<service type="TestPluginAssembly1.Interfaces.IRoom">
<implementation type="TestPluginAssembly1.Implementations.Room"
scope="transient">
<parameters>
<object name="door1" type="TestPluginAssembly1.Interfaces.IDoor"
value="5,185.1" />
<injectedObject name="door2" type="TestPluginAssembly1.Interfaces.IDoor" />
</parameters>
<injectedProperties>
<object name="Door2" type="TestPluginAssembly1.Interfaces.IDoor"
value="7,187.3" />
</injectedProperties>
</implementation>
</service>
</services>
<autoGeneratedServices>
<!--The scope for autoService implementations is always singleton -->
<autoService interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory">
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IEnumerable[TestPluginAssembly1.Interfaces.IResourceAccessValidator]"
reuseValue="true" >
<methodSignature>
<string paramName="resourceName"/>
</methodSignature>
<if parameter1="public_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</if>
<if parameter1="admin_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
</collection>
</if>
<default>
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
|
Element pluginImplementation¶
The element iocConfiguration/pluginsSetup/pluginSetup/pluginImplementation is used to specify an implementation of interface IoC.Configuration.IPlugin for the plugin. The easiest way to provide an implementation of IoC.Configuration.IPlugin is to extend the abstract class IoC.Configuration.PluginAbstr and to override the abstract methods IoC.Configuration.PluginAbstr.Initialize() and IoC.Configuration.PluginAbstr.Dispose(). PluginAbstr implements IoC.Configuration.IPlugin.
Note
Plugins are integrated into dependency injection mechanism. Therefore, the constructor parameters of IoC.Configuration.IPlugin implementations specified in pluginImplementation elements will be injected using the bindings specified in XML Configuration file or in modules referenced by the configuration file. Also, parameters and injectedProperties elements can used with pluginImplementation element to specify constructor parameters or property injection.
Here is an example of implementation of IoC.Configuration.IPlugin interface that is referenced in element iocConfiguration/pluginsSetup/pluginSetup/pluginImplementation in example above:
public class Plugin1 : IoC.Configuration.PluginAbstr
{
private readonly List<SettingInfo> _requiredSettings;
public Plugin1(long param1)
{
Property1 = param1;
_requiredSettings = new List<SettingInfo>();
_requiredSettings.Add(new SettingInfo("Int32Setting1", typeof(int)));
_requiredSettings.Add(new SettingInfo("StringSetting1", typeof(string)));
}
public override IEnumerable<SettingInfo> RequiredSettings => _requiredSettings;
public override void Dispose()
{
// Dispose resources
}
public override void Initialize()
{
// Do initialization here
}
public long Property1 { get; }
public long Property2 { get; set; }
}
Getting Plugin Data at Runtime¶
- To access an instance of IoC.Configuration.IPlugin for specific plugin, inject type IoC.Configuration.IPluginDataRepository (using constructor or property injection), and use the method IPluginData GetPluginData(string pluginName) in interface IoC.Configuration.IPluginDataRepository.
An example is demonstrated below:
public class AccessPluginDataExample
{
public AccessPluginDataExample(IoC.Configuration.IPluginDataRepository pluginDataRepository)
{
var pluginData = pluginRepository.GetPluginData("Plugin1");
Assert.AreEqual(35, pluginData.Property2);
Assert.AreEqual(25,
pluginData.Settings.GetSettingValueOrThrow<int>("Int32Setting1"));
}
}
Element typeDefinition in plugin section¶
Element iocConfiguration/pluginsSetup/pluginSetup/typeDefinitions/typeDefinition can be used in plugin section to reference types by type alias, the same way this element is used in non-plugin section.
Refer to Using Types in Configuration File for more details on typeDefinition element.
Example of typeDefintion elements in pluginSetup element:¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <pluginsSetup>
<pluginSetup plugin="Plugin1">
<pluginImplementation type="TestPluginAssembly1.Implementations.Plugin1_Simple" />
<typeDefinitions>
<!--Generic1_1_of_Interface1_Impl1 type definition overrides the
definition in non-plugins section.-->
<typeDefinition alias="ReadOnlyListOfGenericType"
type="System.Collections.Generic.IReadOnlyList" assembly="corlib">
<genericTypeParameters>
<typeDefinition type="SharedServices.Implementations.Generic.Generic3_1" >
<genericTypeParameters>
<typeDefinition
type="SharedServices.Implementations.Interface1_Impl1" />
</genericTypeParameters>
</typeDefinition>
</genericTypeParameters>
</typeDefinition>
<typeDefinition alias="IDoor" type="TestPluginAssembly1.Interfaces.IDoor" />
<typeDefinition alias="Door" type="TestPluginAssembly1.Implementations.Door" />
<typeDefinition alias="plugin1Module" type="ModulesForPlugin1.IoC.DiModule2" />
</typeDefinitions>
</pluginSetup>
<pluginsSetup>
|
Plugin Settings¶
An element iocConfiguration/pluginsSetup/pluginSetup/settings can be used to specify plugin specific settings. The format of plugin settings is similar to settings in general area (i.e., in element iocConfiguration/settings). For more details on settings in general refer to Settings.
<!--...-->
<pluginSetup plugin="Plugin1">
<!--...-->
<settings>
<int32 name="Int32Setting1" value="25" />
<int64 name="Int64Setting1" value="38" />
<string name="StringSetting1" value="String Value 1" />
</settings>
<!--...-->
</pluginSetup>
Here is an example of how to access plugin setting values at runtime:
public class AccessPluginDataExample
{
public AccessPluginDataExample(IoC.Configuration.IPluginDataRepository pluginDataRepository)
{
var pluginData = pluginRepository.GetPluginData("Plugin1");
Assert.AreEqual(25,
pluginData.Settings.GetSettingValueOrThrow<int>("Int32Setting1"));
Assert.AreEqual("String Value 1",
pluginData.Settings.GetSettingValueOrThrow<string>("StringSetting1"));
}
}
- If a setting is not found in plugin settings element iocConfiguration/pluginsSetup/pluginSetup/settings, IoC.Configuration will search for a setting in general settings area (i.e., in settings defined in element iocConfiguration/settings).
- To specify required settings, implement the property IEnumerable<SettingInfo> RequiredSettings { get; } in interface IoC.Configuration.IPlugin, or override the virtual property with the same name in IoC.Configuration.PluginAbstr, if the plugin implementation is a subclass of IoC.Configuration.PluginAbstr class.
Plugin Modules¶
- Plugin modules can be specified in module elements under element iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/modules.
- The format of iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/modules is similar to the format of element iocConfiguration/dependencyInjection/modules, except that plugin modules are used to specify type bindings for plugin related types. See Modules for more details on iocConfiguration/dependencyInjection/modules element.
Plugin Type Bindings¶
Plugin related type binding can be specified either under element iocConfiguration/dependencyInjection/services to provide plugin related implementations for non plugin interfaces, or under element iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/services for cases when both the service and the implementation are plugin specific.
Note
If the plugin is disabled by setting the value of attribute enabled in element iocConfiguration/plugins/plugin for the specific plugin, the type bindings for the given plugin will be ignored.
Example 1: Plugin Specific Implementation for non Plugin Type¶
Here is an example of binding a non-plugin service SharedServices.Interfaces.IInterface5 to plugin specific type TestPluginAssembly1.Implementations.Interface5_Plugin1Impl.
<iocConfiguration>
<!--...-->
</dependencyInjection>
<!--...-->
<services>
<service type="SharedServices.Interfaces.IInterface5" assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface5_Impl1"
assembly="shared_services"
scope="singleton" />
<implementation type="TestPluginAssembly1.Implementations.Interface5_Plugin1Impl"
assembly="pluginassm1" scope="singleton" />
<implementation type="TestPluginAssembly2.Implementations.Interface5_Plugin2Impl"
assembly="pluginassm2" scope="transient" />
<implementation type="TestPluginAssembly3.Implementations.Interface5_Plugin3Impl"
assembly="pluginassm3" scope="transient" />
</service>
<!--...-->
</services>
<!--...-->
</dependencyInjection>
</iocConfiguration>
Example 2: Plugin Specific Implementation for Plugin Type¶
Here is an example of binding a plugin service TestPluginAssembly1.Interfaces.IDoor to plugin specific type TestPluginAssembly1.Implementations.Door.
<iocConfiguration>
<!--...-->
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<!--...-->
<dependencyInjection>
<services>
<service type="TestPluginAssembly1.Interfaces.IDoor"
assembly="pluginassm1">
<implementation type="TestPluginAssembly1.Implementations.Door"
assembly="pluginassm1"
scope="transient">
<parameters>
<int32 name="Color" value="3" />
<double name="Height" value="180" />
</parameters>
</implementation>
</service>
<!--...-->
</services>
<!--...-->
<dependencyInjection>
</pluginSetup>
<!--...-->
<pluginsSetup>
<!--...-->
<iocConfiguration>
Plugin types in collection in non-plugin section¶
Plugin types can be used in value initializer elements for specifying items in collection element plugin as well as in non-plugin section.
Note
Refer to collection element for more details on collection element.
Note
Refer to Value Initialization Elements for more details on value intialization elements.
If value of plugin type is used in a collection item in non-plugin section, and the plugin is disabled by setting the value of attribute enabled in element iocConfiguration/plugins/plugin for the specific plugin, the item will not be included in a collection generated by IoC.Configuration.
Autogenerated Services¶
An interface with auto-generated implementations can be specified in element iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices. For more information on autogenerated services see Autogenerated Services.
Here is an example of autoGeneratedServices for a plugin. In this example, IoC.Configuration will generate an implementation of TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory and will configure a type binding, that ,apts the interface IResourceAccessValidatorFactory to auto-generated type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <autoGeneratedServices>
<autoService interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory">
<autoMethod name="GetValidators"
returnType="System.Collections.Generic.IEnumerable[TestPluginAssembly1.Interfaces.IResourceAccessValidator]"
reuseValue="true" >
<methodSignature>
<string paramName="resourceName"/>
</methodSignature>
<if parameter1="public_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</if>
<if parameter1="admin_pages">
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
</collection>
</if>
<default>
<collection>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator2"/>
<injectedObject type="TestPluginAssembly1.Interfaces.ResourceAccessValidator1"/>
</collection>
</default>
</autoMethod>
</autoService>
</autoGeneratedServices>
|
The definition of interface IResourceAccessValidatorFactory is shown below
public interface IResourceAccessValidatorFactory
{
IEnumerable<IResourceAccessValidator> GetValidators(string resourceName);
}
Additional Services Provided by IoC.Configuration¶
In addition to registering types specified in XML configuration file and module classes, IoC.Configuration registers bindings for number of other interfaces. Instances of these interfaces can be accessed using constructor or property injection.
Here are some of the interfaces mentioned above:
- IoC.Configuration.DiContainer.IDiContainer: The IoC container.
- IoC.Configuration.ConfigurationFile.IConfiguration: Stores the structure of XML configuration file.
- ISettings: Stores the settings specified in element iocConfiguration/settings (see Settings for more details on settings).
- IoC.Configurati.IPluginDataRepository and IoC.Configuration.ConfigurationFile.IPluginsSetup: Provides access to registered plugins data (see Plugins for more details on plugins).
Troubleshooting Configuration File Errors¶
IoC.Configuration logs helpfull tips on source of configuration file load errors.
Note
Refer to Loading IoC Configuration for details on how to setup the logger.
Example of error logs is shown below:
Fatal:
Exception:Error in element 'settings':
Required setting 'Int32Setting1' should be of type 'System.Int32'. Actual type is 'System.String'. The setting is in plugin settings for plugin 'Plugin1'. To fix the issue, either modify the implementation of method 'RequiredSettings' in class 'TestPluginAssembly1.Implementations.Plugin1', or add the setting.
Element location in configuration file:
<iocConfiguration>
<pluginsSetup>
<pluginSetup plugin="Plugin1">
<settings>
<int64 name="Int64Setting1" value="38"/>
<string name="StringSetting1" value="String Value 1"/>
<string name="Int32Setting1" value="some text"/> <--- Element 'string' is the 3-th child element of element 'settings'.
at IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfiguration.ValidateRequiredSettings(ISettings settings, ISettingsRequestor settingsRequestor)
at IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfiguration.ValidateRequiredSettings(IDiContainer diContainer)
at IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfiguration.OnContainerStarted()
at IoC.Configuration.DiContainerBuilder.DiContainerBuilderConfiguration.StartContainer()
Loading IoC Configuration¶
The dependency injection configuration can be loaded either from modules (see Type Binding In Modules for more details on modules), or from XML Configuration file, in which both type binding as well as module classes can be specified (see XML Configuration File for more details on XML Configuration file).
Before the configuration is loaded, an instance of OROptimizer.Diagnostics.Log.ILogHelperContext should be registered, using OROptimizer.Diagnostics.Log.LogHelper.RegisterContext(ILogHelperContext). An implementation of ILogHelperContext for log4net, OROptimizer.Diagnostics.Log.Log4NetHelperContext, can be found in Nuget package OROptimizer.Shared (referenced by IoC.Configuration library).
Here is an example of registering the logger:
if (!OROptimizer.Diagnostics.Log.LogHelper.IsContextInitialized) OROptimizer.Diagnostics.Log.LogHelper.RegisterContext( new Log4NetHelperContext("MyApp.log4net.config"));
Loading from XML Configuration File¶
An example of XML configuration file can be found at IoCConfiguration_Overview.xml. This file is used in test project IoC.Configuration.Tests.
-The XML Configuration file is validated against XML schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd (see XML Configuration File Schema). -A template XML Configuration file IoC.Configuration.Template.xml can be found in folder IoC.Configuration.Content, where the Nuget package IoC.Configuration is installed (see XML Configuration Template).
To load the IoC configuration from XML configuration file use method IoC.Configuration.DiContainerBuilder.DiContainerBuilder.StartFileBasedDi() as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | using OROptimizer.Xml; // add this using statement to be able to use XmlDocument extensions (i.e., e.XmlDocument.SelectElements("/iocConfiguration/diManagers"), etc.)
// ...
using (var containerInfo =
new DiContainerBuilder.DiContainerBuilder()
.StartFileBasedDi(
new FileBasedConfigurationParameters(
new FileBasedConfigurationFileContentsProvider(
Path.Combine(Helpers.TestsEntryAssemblyFolder, "IoCConfiguration_Overview.xml")),
// Provide the entry assembly folder. Normally this is the folder,
// where the executable file is. However for test projects this might not
// be the case. This folder will be used in assembly resolution.
Helpers.TestsEntryAssemblyFolder,
new LoadedAssembliesForTests())
{
AdditionalReferencedAssemblies = new string[]
{
// List additional assemblies that should be added to dynamically generated assembly as references
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"),
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly2.dll")
},
// Set the value of AttributeValueTransformers to list of
// IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer instances
// to change some xml attribute values when the xml configuration is loaded,
// before the configuration is parsed.
// Good example of implementation of IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer
// is IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.
AttributeValueTransformers = new IAttributeValueTransformer []
{
new FileFolderPathAttributeValueTransformer()
},
ConfigurationFileXmlDocumentLoaded = (sender, e) =>
{
// Replace some elements in e.XmlDocument if needed,
// before the configuration is loaded.
// For example, we can replace the value of attribute 'activeDiManagerName' in element
// iocConfiguration.diManagers to use a different DI manager (say
// switch from Autofac to Ninject).
Helpers.EnsureConfigurationDirectoryExistsOrThrow(e.XmlDocument.SelectElement("/iocConfiguration/appDataDir").GetAttribute("path"));
e.XmlDocument.SelectElements("/iocConfiguration/diManagers")
.First()
.SetAttributeValue("activeDiManagerName", "Autofac");
}
}, out _)
// Note, most of the time we will need to call method WithoutPresetDiContainer().
// However, in some cases, we might need to create an instance of IoC.Configuration.DiContainer.IDiContainer,
// and call the method WithDiContainer(IoC.Configuration.DiContainer.IDiContainer diContainer) instead.
// This might be necessary when using the IoC.Configuration to configure dependency injection in
// ASP.NET Core projects.
// An example implementation of IDIContainer is IoC.Configuration.Autofac.AutofacDiContainer in
// Nuget package IoC.Configuration.Autofac.
.WithoutPresetDiContainer()
// Note, native and IoC.Configuration modules can be specified in XML configuration file, in
// iocConfiguration/dependencyInjection/modules/module elements.
// However, if necessary, AddAdditionalDiModules() and AddNativeModules() can be used to load additional
// IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well
// as native (e.g, Ninject or Autofac) modules.
// Also, AddAdditionalDiModules() and AddNativeModules() can be called multiple times in any order.
.AddAdditionalDiModules(new TestDiModule())
.AddNativeModules(CreateModule<object>("Modules.Autofac.AutofacModule1",
new ParameterInfo[] { new ParameterInfo(typeof(int), 5) }))
.RegisterModules()
.Start())
{
var diContainer = containerInfo.DiContainer;
// Once the configuration is loaded, resolve types using IoC.Configuration.DiContainer.IDiContainer
// Note, interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable,
// and should be disposed, to make sure all the resources are properly disposed of.
var resolvedInstance = containerInfo.DiContainer.Resolve<SharedServices.Interfaces.IInterface7>();
}
|
Once the configuration is loaded into containerInfo variable of type IoC.Configuration.DiContainerBuilder.IContainerInfo, resolve types using property DiContainer in IoC.Configuration.DiContainerBuilder.IContainerInfo (the property is of type IoC.Configuration.DiContainer.IDiContainer).
Interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable.
- Native and IoC.Configuration modules can be specified in XML configuration file, in iocConfiguration/dependencyInjection/modules/module elements. However, if necessary, use the following methods in IoC.Configuration.DiContainerBuilder.FileBased.IFileBasedDiModulesConfigurator to load additional IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well as native (e.g, Ninject or Autofac) modules:
- IFileBasedDiModulesConfigurator.AddAdditionalDiModules(params IDiModule[] diModules)
- IFileBasedDiModulesConfigurator.AddNativeModules(params object[] nativeModules)
Note
These methods can be called multiple times in any order. In other words, we can add some IoC.Configuration modules using AddAdditionalDiModules, then some native modules using AddNativeModules(), then some more IoC.Configuration modules using AddAdditionalDiModules.
Modifying XML Configuration at Runtime¶
The XML Configuration file can be modified at runtime by passing a delegate for parameter configurationFileXmlDocumentLoaded in method IoC.Configuration.DiContainerBuilder.StartFileBasedDi(IConfigurationFileContentsProvider configurationFileContentsProvider, string entryAssemblyFolder, ConfigurationFileXmlDocumentLoadedEventHandler configurationFileXmlDocumentLoaded = null).
This method loads the configuration file into an instance of System.Xml.XmlDocument object, and executes the delegate passed in parameter configurationFileXmlDocumentLoaded.
By the time the delegate is executed, System.Xml.XmlDocument object is not yet validated against the XML schema file IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd (this is done after the delegate is executed). Therefore, the changes to System.Xml.XmlDocument object should be done in such a way that the XML document is still valid against this schema file.
Example of modifying the XML document at runtime to replace the value of attribute activeDiManagerName in element /iocConfiguration/diManagers with Autofac is shown below (this is copied from the C# code above).
new DiContainerBuilder.DiContainerBuilder()
.StartFileBasedDi(
// Other parameters...
(sender, e) =>
{
e.XmlDocument.SelectElements("/iocConfiguration/diManagers").First()
.SetAttributeValue("activeDiManagerName", "Autofac");
})
Loading from Modules¶
To load the IoC configuration from XML configuration file use method IoC.Configuration.DiContainerBuilder.DiContainerBuilder.StartCodeBasedDi() as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | var assemblyProbingPaths = new[]
{
@"K:\...\TestDlls\ThirdPartyLibs",
@"K:\...\TestDlls\ContainerImplementations\Autofac"
};
using (var containerInfo = new DiContainerBuilder.DiContainerBuilder()
// Class IoC.Configuration.DiContainerBuilder.DiContainerBuilder has two overloaded methods StartCodeBasedDi(...)
// DiContainerBuilder.StartCodeBasedDi(IoC.Configuration.DiContainer.IDiManager diManager,...) and
// DiContainerBuilder.StartCodeBasedDi(string diManagerClassFullName, string diManagerClassAssemblyFilePath,...).
// if the project references the library with implementation of IoC.Configuration.DiContainer.IDiManager,
// the first one can be used. Otherwise the second overloaded method can be used, in which case reflection will be used to
// create an instance of IoC.Configuration.DiContainer.IDiManager.
.StartCodeBasedDi("IoC.Configuration.Autofac.meake cleanAutofacDiManager",
@"K:\...\TestDlls\ContainerImplementations\Autofac\IoC.Configuration.Autofac.dll",
new ParameterInfo[0], Helpers.TestsEntryAssemblyFolder, assemblyProbingPaths)
// Note, most of the time we will need to call method WithoutPresetDiContainer().
// However, in some cases, we might need to create an instance of IoC.Configuration.DiContainer.IDiContainer,
// and call the method WithDiContainer(IoC.Configuration.DiContainer.IDiContainer diContainer) instead.
// This might be necessary when using the IoC.Configuration to configure dependency injection in
// ASP.NET Core projects.
// An example implementation of IDIContainer is IoC.Configuration.Autofac.AutofacDiContainer in
// Nuget package IoC.Configuration.Autofac.
.WithoutPresetDiContainer()
// The methods AddDiModules(params IDiModule[] diModules),
// AddNativeModules(params object[] nativeModules), and
// AddNativeModules(string nativeModuleClassFullName, string nativeModuleClassAssemblyFilePath, ...)
// are used to load IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well
// as native (e.g, Ninject or Autofac) modules.
// Also, these three methods can be called multiple times in any order.
.AddDiModules(new TestDiModule())
.AddNativeModule("Modules.Autofac.AutofacModule1",
@"K:\...\TestDlls\DynamicallyLoadedDlls\TestProjects.Modules.dll",
new ParameterInfo[] { new ParameterInfo(typeof(int), 5) })
.RegisterModules()
.Start())
{
var diContainer = containerInfo.DiContainer;
// Once the configuration is loaded, resolve types using IoC.Configuration.DiContainer.IDiContainer
// Note, interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable,
// and should be disposed, to make sure all the resources are properly disposed of.
var resolvedInstance = containerInfo.DiContainer.Resolve<IInterface2>();
}
|
Once the configuration is loaded into containerInfo variable of type IoC.Configuration.DiContainerBuilder.IContainerInfo, resolve types using property DiContainer in IoC.Configuration.DiContainerBuilder.IContainerInfo (the property is of type IoC.Configuration.DiContainer.IDiContainer).
Interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable.
- Use one of the following overloaded methods in class IoC.Configuration.DiContainerBuilder.DiContainerBuilder to specify an instance of IoC.Configuration.DiContainer.IDiManager, that handles the type resolutions and translates the bindings in IoC.Configuration modules into native container bindings (e.g., Autofac and Ninject bindings).
- DiContainerBuilder.StartCodeBasedDi(IDiManager diManager, string entryAssemblyFolder, params string[] assemblyProbingPaths)
- DiContainerBuilder.StartCodeBasedDi(string diManagerClassFullName, string diManagerClassAssemblyFilePath, ParameterInfo[] diManagerConstructorParameters, string entryAssemblyFolder, params string[] assemblyProbingPaths). This method is handy if the project does not reference the assembly with implementation of IoC.Configuration.DiContainer.IDiManager. IoC.Configuration will use refelction to load the type.
Note
Currently two implementations of IoC.Configuration.DiContainer.IDiManager are available: IoC.Configuration.Autofac.AutofacDiManager and IoC.Configuration.Ninject.NinjectDiManager. These implementations are available in Nuget packages IoC.Configuration.Autofac and IoC.Configuration.Ninject
- The following methods in interface IoC.Configuration.DiContainerBuilder.CodeBased.ICodeBasedDiModulesConfigurator can be used to load IoC.Configuration modules IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well as native (e.g, Ninject or Autofac) modules:
- ICodeBasedDiModulesConfigurator.AddDiModules(params IoC.Configuration.DiContainer.IDiModule[] diModules)
- ICodeBasedDiModulesConfigurator.AddNativeModules(params object[] nativeModules)
- ICodeBasedDiModulesConfigurator.AddNativeModule(string nativeModuleClassFullName, string nativeModuleClassAssemblyFilePath, ParameterInfo[] nativeModuleConstructorParameters)
Note
These methods can be called multiple times in any order.
Resolving Types¶
To resolve the types, we first need to load the configuration into an instance of IoC.Configuration.DiContainerBuilder.IContainerInfo.
Refer to sections Loading from XML Configuration File and Loading from Modules for more details.
Here is an example of loading from XML Configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | using OROptimizer.Xml; // add this using statement to be able to use XmlDocument extensions (i.e., e.XmlDocument.SelectElements("/iocConfiguration/diManagers"), etc.)
// ...
using (var containerInfo =
new DiContainerBuilder.DiContainerBuilder()
.StartFileBasedDi(
new FileBasedConfigurationParameters(
new FileBasedConfigurationFileContentsProvider(
Path.Combine(Helpers.TestsEntryAssemblyFolder, "IoCConfiguration_Overview.xml")),
// Provide the entry assembly folder. Normally this is the folder,
// where the executable file is. However for test projects this might not
// be the case. This folder will be used in assembly resolution.
Helpers.TestsEntryAssemblyFolder,
new LoadedAssembliesForTests())
{
AdditionalReferencedAssemblies = new string[]
{
// List additional assemblies that should be added to dynamically generated assembly as references
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"),
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly2.dll")
},
// Set the value of AttributeValueTransformers to list of
// IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer instances
// to change some xml attribute values when the xml configuration is loaded,
// before the configuration is parsed.
// Good example of implementation of IoC.Configuration.AttributeValuesProvider.IAttributeValueTransformer
// is IoC.Configuration.Tests.FileFolderPathAttributeValueTransformer.
AttributeValueTransformers = new IAttributeValueTransformer []
{
new FileFolderPathAttributeValueTransformer()
},
ConfigurationFileXmlDocumentLoaded = (sender, e) =>
{
// Replace some elements in e.XmlDocument if needed,
// before the configuration is loaded.
// For example, we can replace the value of attribute 'activeDiManagerName' in element
// iocConfiguration.diManagers to use a different DI manager (say
// switch from Autofac to Ninject).
Helpers.EnsureConfigurationDirectoryExistsOrThrow(e.XmlDocument.SelectElement("/iocConfiguration/appDataDir").GetAttribute("path"));
e.XmlDocument.SelectElements("/iocConfiguration/diManagers")
.First()
.SetAttributeValue("activeDiManagerName", "Autofac");
}
}, out _)
// Note, most of the time we will need to call method WithoutPresetDiContainer().
// However, in some cases, we might need to create an instance of IoC.Configuration.DiContainer.IDiContainer,
// and call the method WithDiContainer(IoC.Configuration.DiContainer.IDiContainer diContainer) instead.
// This might be necessary when using the IoC.Configuration to configure dependency injection in
// ASP.NET Core projects.
// An example implementation of IDIContainer is IoC.Configuration.Autofac.AutofacDiContainer in
// Nuget package IoC.Configuration.Autofac.
.WithoutPresetDiContainer()
// Note, native and IoC.Configuration modules can be specified in XML configuration file, in
// iocConfiguration/dependencyInjection/modules/module elements.
// However, if necessary, AddAdditionalDiModules() and AddNativeModules() can be used to load additional
// IoC.Configuration modules (instances of IoC.Configuration.DiContainer.IDiModule), as well
// as native (e.g, Ninject or Autofac) modules.
// Also, AddAdditionalDiModules() and AddNativeModules() can be called multiple times in any order.
.AddAdditionalDiModules(new TestDiModule())
.AddNativeModules(CreateModule<object>("Modules.Autofac.AutofacModule1",
new ParameterInfo[] { new ParameterInfo(typeof(int), 5) }))
.RegisterModules()
.Start())
{
var diContainer = containerInfo.DiContainer;
// Once the configuration is loaded, resolve types using IoC.Configuration.DiContainer.IDiContainer
// Note, interface IoC.Configuration.DiContainerBuilder.IContainerInfo extends System.IDisposable,
// and should be disposed, to make sure all the resources are properly disposed of.
var resolvedInstance = containerInfo.DiContainer.Resolve<SharedServices.Interfaces.IInterface7>();
}
|
Once the IoC is loaded into IoC.Configuration.DiContainerBuilder.IContainerInfo, use methods in IoC.Configuration.DiContainerBuilder.IContainerInfo.DiContainer to resolve types.
Examples of resolving types:
// diContainer is created from XML configuration file or modules.
IoC.Configuration.DiContainerBuilder.IContainerInfo.DiContainer diContainer;
var instance1 = diContainer.Resolve(typeof(IInterface3));
var instance2 = diContainer.Resolve<IInterface3>();
using (var lifeTimeScope = diContainer.StartLifeTimeScope())
{
var instance3 = diContainer.Resolve<IInterface1>(lifeTimeScope);
var instance4 = diContainer.Resolve(typeof(IInterface3), lifeTimeScope);
}
Example of injecting a type into a constructor
public class TestTypeResolution
{
private IInterface3 _instanceOfInterface3;
// An instance of IInterface3 will be injected into constructor of TestTypeResolution
// based on binding specified for type IInterface3 in XML configuration file or in IoC.Configuration
// or native modules.
public TestTypeResolution(IInterface3 instanceOfInterface3)
{
_instanceOfInterface3 = instanceOfInterface3;
}
}
When the type is re-solved, the bindings specified in configuration file (see XML Configuration File) or in module classes (see Type Binding In Modules) are used to recursively inject constructor parameters, or to set the property values of resolved types (if property injection is specified in configuration file or in modules).
Resolution Scopes¶
Resolution scope determines if the same object or different objects will be returned by the container on subsequent requests of type.
IoC.Configuration supports three types of resolution scopes: Singleton, ScopeLifetime, and Transient scopes.
Scope: Singleton¶
Singleton scope results in type being resolved to the same instance on subsequent requests.
Here is an example of specifying Singleton resolution scope in method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations() (see Type Bindings in IoC.Configuration Modules):
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<SharedServices.Interfaces.IInterface9>()
.To<SharedServices.Implementations.Interface9_Impl1>()
.SetResolutionScope(DiResolutionScope.Singleton);
}
}
Here is an example of specifying Singleton resolution scope in XML configuration file (see Service Bindings):
<service type="SharedServices.Interfaces.IInterface9" assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface9_Impl1"
assembly="shared_services"
scope="singleton" />
</service>
Here is an example of resolving types bound with Singleton scope resolution
private void SingletonScopeResolutionExample(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
var service1 = diContainer.Resolve<IInterface9>();
var service2 = diContainer.Resolve<IInterface9>();
Assert.AreSame(service1, service2);
}
Scope: Transient¶
Transient scope results in type being resolved to a newly created instance on each requests.
Here is an example of specifying Transient resolution scope in method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations() (see Type Bindings in IoC.Configuration Modules):
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<DynamicallyLoadedAssembly1.Interfaces.IInterface2>()
.To<SharedServices.DynamicallyLoadedAssembly1.Implementations.Interface2_Impl1>()
.SetResolutionScope(DiResolutionScope.Transient);
}
}
Here is an example of specifying Transient resolution scope in XML configuration file (see Service Bindings):
<service type="DynamicallyLoadedAssembly1.Interfaces.IInterface2"
assembly="dynamic1">
<implementation type="DynamicallyLoadedAssembly1.Implementations.Interface2_Impl1"
assembly="dynamic1"
scope="transient">
</implementation>
</service>
Here is an example of resolving types bound with Transient scope resolution
private void TransientScopeResolutionExample(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
Type typeInterface2 = Helpers.GetType("DynamicallyLoadedAssembly1.Interfaces.IInterface2");
var service1 = diContainer.Resolve(typeInterface2);
var service2 = diContainer.Resolve(typeInterface2);
Assert.AreNotSame(service1, service2);
}
Scope: ScopeLifetime¶
ScopeLifetime scope results in type being resolved to the same instance on subsequent requests, if the same instance of IoC.Configuration.DiContainer.ILifeTimeScope is used as a parameter to method diContainer.Resolve(Type typeToResolve, ILifeTimeScope lifetimeScope).
Note
If DiResolutionScope.ScopeLifetime is not used when specifying the binding for the type, the value passed for ILifeTimeScope parameter in diContainer.Resolve(Type typeToResolve, ILifeTimeScope lifetimeScope) does not matter, and the type will be resolved with resolution scope used in type binding (e.g., Singleton, Transient).
Here is an example of specifying ScopeLifetime resolution scope in method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations() (see Type Bindings in IoC.Configuration Modules):
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<DynamicallyLoadedAssembly1.Interfaces.IInterface3>()
.To<DynamicallyLoadedAssembly1.Implementations.Interface3_Impl1>()
.SetResolutionScope(DiResolutionScope.ScopeLifetime);
}
}
Here is an example of specifying ScopeLifetime resolution scope in XML configuration file (see Service Bindings):
<service type="DynamicallyLoadedAssembly1.Interfaces.IInterface3" assembly="dynamic1">
<implementation type="DynamicallyLoadedAssembly1.Implementations.Interface3_Impl1"
assembly="dynamic1"
scope="scopeLifetime">
</implementation>
</service>
Here is an example of resolving types bound with ScopeLifetime scope resolution:
private void LifetimeScopeResolutionExample(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
Type typeInterface3 = Helpers.GetType(
"DynamicallyLoadedAssembly1.Interfaces.IInterface3");
// Same objects are created in default lifetime scope.
var service1InMainScope = diContainer.Resolve(typeInterface3);
var service2InMainScope = diContainer.Resolve(typeInterface3);
Assert.AreSame(service1InMainScope, service2InMainScope);
using (var lifeTimeScope = diContainer.StartLifeTimeScope())
{
// IDiContainer.Resolve(Type, ILifetimeScope) returns
// the same object for the same scope lifeTimeScope.
var service1InScope1 = diContainer.Resolve(typeInterface3, lifeTimeScope);
var service2InScope1 = diContainer.Resolve(typeInterface3, lifeTimeScope);
Assert.AreSame(service1InScope1, service2InScope1);
// However, the objects are different from the ones created in main
// lifetime scope.
Assert.AreNotSame(service1InScope1, service1InMainScope);
}
}
Multiple Bindings¶
If we know that only one binding for the type was specified in configuration file (see XML Configuration File) or in modules (see Type Binding In Modules), we can resolve the type by specifying the type as a parameter to method IoC.Configuration.DiContainer.IDiContainer.Resove(Type), as shown below:
private void ResolvingATypeWithSingleBinding(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
Type typeInterface2 = Helpers.GetType("DynamicallyLoadedAssembly1.Interfaces.IInterface2");
var service1 = diContainer.Resolve(typeInterface2);
var service2 = diContainer.Resolve(typeInterface2);
Assert.AreNotSame(service1, service2);
}
However, multiple bindings might be specified for the same type as well. Below are examples of specifying multiple bindings for the same type in configuration file, and in overridden method in method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations().
Example of multiple bindings for type in XML configuration file:
<service type="SharedServices.Interfaces.IInterface5" assembly="shared_services">
<implementation type="SharedServices.Implementations.Interface5_Impl1"
assembly="shared_services"
scope="singleton" />
<implementation type="TestPluginAssembly1.Implementations.Interface5_Plugin1Impl"
assembly="pluginassm1" scope="singleton" />
<implementation type="TestPluginAssembly2.Implementations.Interface5_Plugin2Impl"
assembly="pluginassm2" scope="transient" />
</service>
Example of multiple bindings for type in overridden method in method IoC.Configuration.DiContainer.ModuleAbstr.AddServiceRegistrations():
public class TestDiModule : IoC.Configuration.DiContainer.ModuleAbstr
{
protected override void AddServiceRegistrations()
{
Bind<SharedServices.Interfaces.IInterface5>()
.To<SharedServices.Implementations.Interface5_Impl1>()
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<SharedServices.Interfaces.IInterface5>()
.To<TestPluginAssembly1.Implementations.Interface5_Plugin1Impl>()
.SetResolutionScope(DiResolutionScope.Singleton);
Bind<SharedServices.Interfaces.IInterface5>()
.To<TestPluginAssembly2.Implementations.Interface5_Plugin2Impl>()
.SetResolutionScope(DiResolutionScope.Transient);
}
}
To resolve types that are bound to multiple types, resolve type System.Collections.Generic.IEnumerable<TService>.
Note
We still can resolve to a single type, rather than to a collection. However, not all implementations support this resolution, when multiple bindings exist. For example, Autofac implementation will resolve the type to the last binding, while Ninject implementation will throw an exception.
private void ResolvingATypeWithMultipleBindings(IoC.Configuration.DiContainer.IDiContainer diContainer)
{
var resolvedInstances = diContainer.Resolve<IEnumerable<SharedServices.Interfaces.IInterface5>>()
.ToList();
Assert.AreEqual(3, resolvedInstances.Count);
var typeOfInterface5 = typeof(IInterface5);
Assert.IsInstanceOfType(resolvedInstances[0], typeOfInterface5);
Assert.IsInstanceOfType(resolvedInstances[1], typeOfInterface5);
Assert.IsInstanceOfType(resolvedInstances[2], typeOfInterface5);
}
Application Integration¶
ASP.NET Core¶
IoC.Configuration can be used with ASP.NET Core to replace the dependency injection container that ASP.NET Core uses. This includes also re-solving ASP.NET Core controllers.
Follow these steps to integrate IoC.Configuration with ASP.NET Core.
If necessary, use an element iocConfiguration/webApi (or iocConfiguration/pluginsSetup/pluginsSetup/webApi for configuring controllers for plugins) to list the assemblies that contain ASP.NET Core controllers.
The IoC.Configuration user will have to iterate this assemblies and register them with ASP.NET Core, as will be shown in code in Step 3 below.
Note
Element webApi is optional, and is only needed if we want to use IoC.Configuration to register controllers specified in a different assembly.
Here is an example of webApi element with an assembly with ASP.NET Core controllers:
1 2 3 4 5 6 7 8 9 10
<webApi> <controllerAssemblies> <!-- Specify assemblies with API controllers. The user of IoC.Configuration should add the assemblies to MVC using IMvcBuilder.AddApplicationPart(System.Reflection.Assembly) --> <controllerAssembly assembly="dynamic1"></controllerAssembly> </controllerAssemblies> </webApi>
If any assemblies with ASP.NET Core controllers were specified in Step 1, register bindings for controllers in these assemblies in dependency injection elements iocConfiguration/dependencyInjection/ or iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/.
Here is an exert from the configuration file demonstrating Steps 1 and 2.
- Element webApi on line 9 lists an assembly with an alias smart_xml_docs as an assembly with ASP.NET Core controllers (see Assemblies and Probing Paths on how to register assemblies).
- Element selfBoundService on line 17 specifies a binding for an ASP.NET Core controller WebFileSystemApi.SmartXmlDocs.Controllers.SmartXmlTestController in assembly with alias smart_xml_docs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <pluginsSetup>
<pluginSetup plugin="SmartXmlDocs">
<pluginImplementation
type="WebFileSystemApi.SmartXmlDocs.SmartXmlDocsPlugin"
assembly="smart_xml_docs">
</pluginImplementation>
<settings>
</settings>
<webApi>
<controllerAssemblies>
<controllerAssembly assembly="smart_xml_docs"/>
</controllerAssemblies>
</webApi>
<dependencyInjection>
<modules />
<services>
<selfBoundService
type="WebFileSystemApi.SmartXmlDocs.Controllers.SmartXmlTestController"
assembly="smart_xml_docs" scope="transient" >
</selfBoundService>
</services>
<autoGeneratedServices>
</autoGeneratedServices>
</dependencyInjection>
</pluginSetup>
</pluginsSetup>
|
Here is the code for controller class WebFileSystemApi.SmartXmlDocs.Controllers.SmartXmlTestController:
1 2 3 4 5 6 7 8 9 10 11 12 13 | using Microsoft.AspNetCore.Mvc;
namespace WebFileSystemApi.SmartXmlDocs.Controllers
{
[Route("[controller]/[action]")]
public class SmartXmlTestController : Controller
{
[HttpGet("{smartXmlFileId:long}")]
public string SmartXmlDoc(long smartXmlFileId)
{
return $"Smart XML File Id is {smartXmlFileId}";
}
}
}
|
Finally register IoC.Configuration with ASP.NET Core by using method public IServiceProvider ConfigureServices(IServiceCollection services) in Startup class as shown below. There are detailed code comments in the example below, so no farther explanations are provided.
Note
Integration with ASP.NET Core is currently supported for IoC.Configuration.Autofac. Currently, the ASP.NET Core project will need to reference the Nuget packages Autofac, IoC.Configuration, and IoC.Configuration.Autofac. In future this might be improved to support other containers as well (such as Ninject), and to avoid referencing these packages in the project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | private static IContainerInfo _containerInfo;
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Do some ASP.NET Core configuration
var mvcBuilder = services.AddMvc()
.AddMvcOptions(options =>
{
// ...
})
.AddJsonOptions(options =>
{
// ...
})
.AddControllersAsServices();
var rootDirectory = AppDomain.CurrentDomain.BaseDirectory;
// Load IoC.Configuration into iocContainerBuilder
var iocContainerBuilder =
new DiContainerBuilder()
.StartFileBasedDi(
new FileBasedConfigurationParameters(
new FileBasedConfigurationFileContentsProvider(Path.Combine(rootDirectory, "WebFileSystem.IoC.Configuration.xml")),
rootDirectory, new AllLoadedAssemblies())
{
ConfigurationFileXmlDocumentLoaded = (sender, e) =>
{
// Do XML file transformations here
}
}, out var loadedConfiguration);
// Register controller assemblies in webApi elements in IoC.Configuration file
// with ASP.NET Core.
Action<IoC.Configuration.ConfigurationFile.IWebApi> addControllersFromConfiguration =
(webApi) =>
{
if (webApi == null || webApi.ControllerAssemblies == null)
return;
foreach (var controllerAssembly in webApi.ControllerAssemblies.Assemblies)
{
if (controllerAssembly.LoadedAssembly != null)
mvcBuilder.AddApplicationPart(controllerAssembly.LoadedAssembly);
}
};
// Register controller assemblies in iocConfiguration/webApi element.
addControllersFromConfiguration(loadedConfiguration.WebApi);
// Now register controller assemblies in webApi elements under
// iocConfiguration/pluginsSetup/pluginSetup elements.
foreach (var pluginSetup in loadedConfiguration.PluginsSetup.AllPluginSetups)
{
if (pluginSetup.Enabled)
addControllersFromConfiguration(pluginSetup.WebApi);
}
// Build the Autofac container builder and start the IoC.Configuration.
var autofacContainerBuilder = new ContainerBuilder();
// Register ASP.NET Core services with Autofac, however skip
// the services, the full name of which starts with "WebFileSystemApi".
// Registering bindings of non-Microsoft services will be done in
// IoC.Configuration file.
autofacContainerBuilder.Populate(
services.Where(x =>
!x.ServiceType.FullName.StartsWith("WebFileSystemApi", StringComparison.Ordinal)));
// Since we provide an instance of
// IoC.Configuration.Autofac.AutofacDiContainer,
// IoC.Configuration.Autofac will not create and build instance of
// Autofac.ContainerBuilder.
// In this case, we need to call iocContainerStarter.Start() only after
// we call autofacContainerBuilder.Build() below.
var iocContainerStarter = iocContainerBuilder
.WithDiContainer(new AutofacDiContainer(autofacContainerBuilder))
.RegisterModules();
var container = autofacContainerBuilder.Build();
_containerInfo = iocContainerStarter.Start();
return new AutofacServiceProvider(container);
}
|
1 2 3 4 5 | // Make sure OnShutdown() is called on ASP.NET Core shutdown, to dispose of _containerInfo.
private void OnShutdown()
{
_containerInfo?.Dispose();
}
|
Trouble-shooting¶
Troubleshooting Dynamically Generated Assembly¶
- If configuration is loaded from configuration file, IoC.Configuration generates an assembly file which has a format DynamicallyGeneratedAssembly_timestamp.dll. Example is DynamicallyGeneratedAssembly_637851312217643417.dll.
Note
Refer to Loading from XML Configuration File for details on loading file based configuration
The dynamically generated assembly has classes for auto-generated services in elements autoService and autoServiceCustom under elements iocConfiguration/dependencyInjection/autoGeneratedServices and iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices, as well as some other auto-generated classes.
Note
The file is deleted, and a new file is generated when the configuration is loaded. In the future an improvement might be implemented to re-generate the assembly only if the configuration changed.
The folder where the dynamically generated DLL file is saved is determined by the value of attribute path in element iocConfiguration/appDataDir as in example below
1 2 3 4 5 | <iocConfiguration
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="http://oroptimizer.com/IoC.Configuration/V2/IoC.Configuration.Schema.7579ADB2-0FBD-4210-A8CA-EE4B4646DB3F.xsd">
<appDataDir path="TestFiles\AutogeneratedDlls\DynamicFiles_AutoServiceTests" />
</iocConfiguration>
|
Below are some situations when the auto-generated assembly might fail to load, when configuration is loaded:
- The code generated for autoServiceCustom by an implementation of IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator has invalid code.
- The dynamically generated assembly references classes from other assemblies, and the assemblies that contain the classes are not added as references to dynamically generated assembly. To better resolve this issue, the rules used to add references to dynamically generated assembly are outlined below.
How Referenced Assemblies are Added to Dynamically Generated Assembly¶
There are number of ways, listed below, that IoC.Configuration can be instructed to add references to dynamically generated assembly.
Add referenced assembly file paths in property AdditionalReferencedAssemblies in class IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfigurationParameters, an instanceof which is used when loading the configuration from xml file, as demonstrated below:
Make sure the assembly is included in property OROptimizer.ILoadedAssemblies LoadedAssemblies { get; } in IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfigurationParameters that is used to load the XML configuration file. The property LoadedAssemblies of IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfigurationParameters is initialized in constructor, and in most cases an implementation OROptimizer.AllLoadedAssemblies can be used as demonstrated in example below.
Note
OROptimizer.AllLoadedAssemblies returns all assemblies loaded into application domain in property System.Collections.Generic.IEnumerable<Assembly> GetAssemblies().
Below is a demonstration of using properties AdditionalReferencedAssemblies and LoadedAssemblies in IoC.Configuration.DiContainerBuilder.FileBased.FileBasedConfigurationParameters to add references to dynamically generated assembly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using System.IO;
using IoC.Configuration.DiContainerBuilder.FileBased;
using NUnit.Framework;
using OROptimizer.Utilities.Xml;
using TestsSharedLibrary;
namespace IoC.Configuration.Tests.DocumentationTests.ReferencesInDynamicAssembly;
[TestFixture]
public class FileBasedConfigurationParameters_AdditionalReferencedAssemblies
{
[Test]
public void FileBasedConfigurationParameters_AdditionalReferencedAssemblies_Demo()
{
TestsHelper.SetupLogger();
var fileBasedConfigurationParameters = new FileBasedConfigurationParameters(
new FileBasedConfigurationFileContentsProvider(
Path.Combine(Helpers.TestsEntryAssemblyFolder, @"DocumentationTests\AutoServiceCustom\DemoIoCConfiguration_autoServiceCustom.xml")),
Helpers.TestsEntryAssemblyFolder,
// LoadedAssembliesForTests is an implementation of ILoadedAssemblies that has a method
// "IEnumerable<Assembly> GetAssemblies()" that returns list of assemblies to add as references to
// generate dynamic assembly.
new LoadedAssembliesForTests())
{
AdditionalReferencedAssemblies = new []
{
// List additional assemblies that should be added to dynamically generated assembly as references
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"),
Path.Combine(Helpers.GetTestFilesFolderPath(), @"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly2.dll")
},
AttributeValueTransformers = new[] {new FileFolderPathAttributeValueTransformer()},
ConfigurationFileXmlDocumentLoaded = (sender, e) =>
Helpers.EnsureConfigurationDirectoryExistsOrThrow(e.XmlDocument.SelectElement("/iocConfiguration/appDataDir").GetAttribute("path"))
};
var containerInfo = new DiContainerBuilder.DiContainerBuilder()
.StartFileBasedDi(fileBasedConfigurationParameters, out _)
.WithoutPresetDiContainer()
.RegisterModules().Start();
var autoImplementedInterfaceInstance = containerInfo.DiContainer.Resolve<IoC.Configuration.Tests.DocumentationTests.AutoServiceCustom.ISimpleAutoImplementedInterface1>();
Assert.AreEqual(10, autoImplementedInterfaceInstance.GetValue());
}
}
|
- Include the assembly in one of iocConfiguration/assemblies/assembly elements in configuration file. All assemblies specified in iocConfiguration/assemblies/assembly elements are added as references to dynamically generated assembly. However when the assembly is loaded, referenced assemblies are loaded to domain only if types in these assemblies are used in dynamic assembly.
Note
Refer to Assemblies and Probing Paths for details on using iocConfiguration/assemblies/assembly elements.
Add referenced assemblies in implementation of method GenerateCSharp in interface IoC.Configuration.ConfigurationFile.ICustomAutoServiceCodeGenerator when providing an implementation of an interface specified in element autoServiceCustom. Look at example below.
Note
Refer to Element autoServiceCustom for details on element autoServiceCustom.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | using System;
using System.IO;
using IoC.Configuration.ConfigurationFile;
using IoC.Configuration.DiContainer;
using OROptimizer.DynamicCode;
namespace IoC.Configuration.Tests.DocumentationTests.ReferencesInDynamicAssembly;
public class CustomAutoServiceCodeGeneratorDemo : ICustomAutoServiceCodeGenerator
{
public void GenerateCSharp(ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo,
IDynamicAssemblyBuilder dynamicAssemblyBuilder,
string generatedClassNamespace, string generatedClassName)
{
dynamicAssemblyBuilder.AddReferencedAssembly(
Path.Combine(Helpers.GetTestFilesFolderPath(),
@"DynamicallyLoadedDlls\TestProjects.DynamicallyLoadedAssembly1.dll"));
dynamicAssemblyBuilder.AddReferencedAssembly(
typeof(SharedServices.Interfaces.IInterface1));
var classInfo = dynamicAssemblyBuilder.StartDynamicallyGeneratedClass(
generatedClassName, generatedClassNamespace);
var methodInfo = classInfo.StartMethod("GetValue", typeof(int),
Array.Empty<IMethodParameterInfo>(),
AccessLevel.Public, false, false);
methodInfo.AddCodeLine("=> 10;");
}
public void Validate(ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo)
{
}
public void ValidateOnIoCContainerLoaded(IDiContainer diContainer,
ICustomAutoGeneratedServiceInfo customAutoGeneratedServiceInfo)
{
}
}
|