Element autoService
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:
1namespace IoC.Configuration.Tests.AutoService.Services
2{
3 public interface IActionValidatorFactoryBase
4 {
5 IReadOnlyList<IActionValidator> GetValidators(int actionTypeId, string projectGuid);
6 }
7
8 public interface IActionValidatorFactory : IActionValidatorFactoryBase
9 {
10 Guid PublicProjectId { get; }
11 IActionValidator DefaultActionValidator { get; }
12 IReadOnlyList<IActionValidator> GetValidators(ActionTypes actionType, Guid projectGuid);
13 void SomeMethodNotInConfigFile(int param1, string param2);
14 int SomePropertyNotInConfigFile { get; }
15 }
16}
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 ./auto-property and ./auto-method
1<dependencyInjection>
2 <!--Some other service bindings specified here-->
3 <autoGeneratedServices>
4 <autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
5
6 <autoProperty name="DefaultActionValidator"
7 returnType="SharedServices.Interfaces.IActionValidator">
8 <injectedObject
9 type="IoC.Configuration.Tests.AutoService.Services.ActionValidatorDefault"/>
10 </autoProperty>
11
12 <autoProperty name="PublicProjectId" returnType="System.Guid">
13 <object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/>
14 </autoProperty>
15
16 <autoMethod name="GetValidators"
17 returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]"
18 reuseValue="true">
19 <methodSignature>
20 <!--paramName attribute is optional, however it
21 makes the auto-implementation more readable. -->
22 <object paramName="actionType" typeRef="ActionTypes"/>
23 <object paramName="projectGuid" type="System.Guid"/>
24 </methodSignature>
25
26 <if parameter1="_classMember:SharedServices.DataContracts.ActionTypes.ViewFilesList"
27 parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
28 <collection>
29
30 <constructedValue type="SharedServices.Implementations.ActionValidator1">
31 <parameters>
32 <int32 name="intParam" value="7"/>
33 </parameters>
34 </constructedValue>
35
36 <injectedObject type="SharedServices.Implementations.ActionValidator3"/>
37
38 <!--Plugin1ActionValidator belongs to Plugin1. If we disable this plugin,
39 the injectedObject element below will not be included in
40 returned collection.-->
41 <injectedObject type="TestPluginAssembly1.Implementations.Plugin1ActionValidator"/>
42 </collection>
43 </if>
44
45 <if parameter1="_classMember:SharedServices.DataContracts.ActionTypes.ViewFileContents"
46 parameter2="F981F171-B382-4F15-A8F9-FE3732918D3F">
47 <collection>
48 <injectedObject type="SharedServices.Implementations.ActionValidator1"/>
49 </collection>
50 </if>
51
52 <!--If none of conditions above are true, the default value will be returned by
53 interface implementation.-->
54 <default>
55 <collection>
56 <!--We can also call a method or property in auto-generated interface, or in
57 one of its base interfaces.-->
58 <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"
59 memberName="DefaultActionValidator"/>
60
61 <injectedObject type="SharedServices.Implementations.ActionValidator3"/>
62
63 <injectedObject type="DynamicallyLoadedAssembly2.ActionValidator4"/>
64 </collection>
65 </default>
66 </autoMethod>
67
68 <!--Overloaded method GetValidators uses parameters of types System.Int32 and System.string,
69 instead of SharedServices.DataContracts.ActionTypes and System.Guid, as in case above.-->
70 <autoMethod name="GetValidators"
71 returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]">
72 <methodSignature>
73 <!--paramName attribute is optional, however it makes the auto-implementation
74 more readable. -->
75 <int32 paramName="actionTypeId"/>
76 <string paramName="projectGuid"/>
77 </methodSignature>
78
79 <!-- Attributes parameter1 and parameter2 map values of parameters param1 and param2 in
80 GetInstances() method to returned values. -->
81 <if parameter1="0" parameter2="8663708F-C707-47E1-AEDC-2CD9291AD4CB">
82 <collection>
83 <injectedObject type="SharedServices.Implementations.ActionValidator3"/>
84 <injectedObject type="IoC.Configuration.Tests.AutoService.Services.ActionValidator4"/>
85 </collection>
86 </if>
87
88 <default>
89 <collection>
90 <!--We can also call a method or property in auto-generated interface, or
91 in one of its base interfaces.-->
92 <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory"
93 memberName="DefaultActionValidator"/>
94 <injectedObject type="SharedServices.Implementations.ActionValidator3"/>
95 <classMember class="IoC.Configuration.Tests.AutoService.Services.StaticAndConstMembers"
96 memberName="GetDefaultActionValidator"/>
97 <classMember class="IoC.Configuration.Tests.AutoService.Services.IActionValidatorValuesProvider"
98 memberName="AdminLevelActionValidator"/>
99 </collection>
100 </default>
101 </autoMethod>
102 </autoService>
103 </autoGeneratedServices>
104</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));
}
}
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<autoMethod name="GetValidators"
2 returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]">
3
4 <!--method signature and return value elements go here...-->
5</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<!--autoMethod below is a configuration for a C# method
2System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator] GetValidators(
3 SharedServices.DataContracts.ActionTypes actionType,
4 System.Guid projectGuid,
5 int someIntParam)-->
6<autoMethod name="GetValidators"
7 returnType="System.Collections.Generic.IReadOnlyList[SharedServices.Interfaces.IActionValidator]">
8
9 <methodSignature>
10 <!--paramName attribute is optional, however it
11 makes the auto-implementation more readable. -->
12 <object paramName="actionType" typeRef="ActionTypes"/>
13 <object paramName="projectGuid" type="System.Guid"/>
14 <int32 paramName="someIntParam" />
15 </methodSignature>
16
17 <!--return value elements go here..-->
18</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<autoGeneratedServices>
2 <!--Demo of referencing auto-implemented method parameters using
3 parameterValue element-->
4 <autoService
5 interface="IoC.Configuration.Tests.AutoService.Services.IAppInfoFactory">
6
7 <autoMethod name="CreateAppInfo"
8 returnType="IoC.Configuration.Tests.AutoService.Services.IAppInfo">
9
10 <methodSignature>
11 <int32 paramName="appId"/>
12 <string paramName="appDescription"/>
13 </methodSignature>
14
15 <default>
16 <constructedValue
17 type="IoC.Configuration.Tests.AutoService.Services.AppInfo">
18 <parameters>
19 <!--The value of name attribute is the name of constructor parameter
20 in AppInfo-->
21 <!--
22 The value of paramName attribute is the name of parameter in
23 IAppInfoFactory.CreateAppInfo.
24 This parameter should be present under autoMethod/methodSignature element.
25 -->
26 <!--In this example the values of name and paramName are similar, however
27 they don't have to be.-->
28 <parameterValue name="appId" paramName="appId" />
29 <parameterValue name="appDescription" paramName="appDescription" />
30 </parameters>
31 </constructedValue>
32 </default>
33 </autoMethod>
34 </autoService>
35</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<autoService
2 interface="TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory">
3 <autoMethod name="GetValidators"
4 returnTypeRef="IEnumerableOfIResourceAccessValidator"
5 reuseValue="true" >
6 <!--method signature and return value elements go here...-->
7 </autoMethod>
8 <!--Some other autoMethod and autoProperty elements go here -->
9</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<!-- 2IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo demonstrates cases 3when there are multiple occurrences of auto-generated methods and properties with 4same signatures and return types in its base interfaces. 5--> 6<autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo"> 7 8 <!--GetIntValues(): IReadOnlyList<int> GetIntValues(int param1, string param2)--> 9 <autoMethod name="GetIntValues" 10 returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" > 11 <methodSignature> 12 <int32 paramName="param1"/> 13 <string paramName="param2"/> 14 </methodSignature> 15 <if parameter1="1" parameter2="str1"> 16 <collection> 17 <int32 value="17"/> 18 </collection> 19 </if> 20 <default> 21 <collection> 22 <int32 value="18"/> 23 <int32 value="19"/> 24 </collection> 25 </default> 26 </autoMethod> 27 28 <!-- 29 This method is declared in IMemberAmbiguityDemo_Parent3, which is a base interface for 30 IMemberAmbiguityDemo. 31 We can provide implementation for this interface, even though it has a similar signature 32 and return type as the method 33 IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo.GetIntValues. 34 By using the attribute 'declaringInterface', we make a distinction between these two. 35 --> 36 <autoMethod name="GetIntValues" 37 returnType="System.Collections.Generic.IReadOnlyList[System.Int32]" 38 declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent3"> 39 <methodSignature> 40 <int32 paramName="param1"/> 41 <string paramName="param2"/> 42 </methodSignature> 43 <default> 44 <collection> 45 <int32 value="3"/> 46 </collection> 47 </default> 48 </autoMethod> 49</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<autoService interface="IoC.Configuration.Tests.AutoService.Services.IActionValidatorFactory">
2 <autoProperty name="PublicProjectId" returnType="System.Guid" >
3 <object type="System.Guid" value="95E352DD-5C79-49D0-BD51-D62153570B61"/>
4 </autoProperty>
5</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<!-- 2IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo demonstrates 3cases when there are multiple occurrences of auto-generated methods and properties 4with same signatures and return types in base interfaces of 5IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo. 6--> 7<autoService interface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo"> 8 <!-- 9 Both IMemberAmbiguityDemo_Parent1 and IMemberAmbiguityDemo_Parent2 have properties called DefaultDbConnection 10 with the same return types. We can auto-implement this property for each of these interfaces by using 11 declaringInterface attribute in autoProperty element to explicitly specify the interface that own 12 the property (declaringInterface can be used in autoMethod as well as demonstrated above) 13 --> 14 <!--Auto-implementation of IMemberAmbiguityDemo_Parent1.DefaultDbConnection--> 15 <autoProperty name="DefaultDbConnection" 16 returnType="SharedServices.Interfaces.IDbConnection" 17 declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent1"> 18 <constructedValue type="SharedServices.Implementations.SqliteDbConnection"> 19 <parameters> 20 <string name="filePath" value="c:\IMemberAmbiguityDemo_Parent1_Db.sqlite"/> 21 </parameters> 22 </constructedValue> 23 </autoProperty> 24 25 <!--Auto-implementation of IMemberAmbiguityDemo_Parent2.DefaultDbConnection--> 26 <autoProperty name="DefaultDbConnection" 27 returnType="SharedServices.Interfaces.IDbConnection" 28 declaringInterface="IoC.Configuration.Tests.AutoService.Services.IMemberAmbiguityDemo_Parent2"> 29 <constructedValue type="SharedServices.Implementations.SqliteDbConnection"> 30 <parameters> 31 <string name="filePath" value="c:\IMemberAmbiguityDemo_Parent2_Db.sqlite"/> 32 </parameters> 33 </constructedValue> 34 </autoProperty> 35</autoService>