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.

      Note

      Refer to Settings or Plugins for more details on general and plugin settings.

      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>