Adapting the client to use your own resource definitions

Basics: RmResource and strongly-typed resources

The Microsoft.ResourceManagement.ObjectModel assembly in the client code contains the definitions of the FIM resources.
The base class for any FIM object (persons, groups, sets, synchronization rules, whatever) is RmResource. RmResource is basically a dictionary, that allows you to get an attribute value given its name:

// create a generic resource
RmResource resource = new RmResource();
// set its type
resource.ObjectType = "Person";
// set one of its attributes: note that you have to use one of the 
// "generic" attribute value classes:
resource["AccountName"] = new RmAttributeValueSingle("guest");

For convenience, some strongly-typed resources are provided with the client. For example, RmPerson extends the RmResource class for Person objects. The previous example would become:

// Do the same thing with a strongly-typed resource. No need to set
// the ObjectType property.
RmPerson person = new RmPerson();
// Set the AccountName. The strongly-typed resource knows that the
// property is a single-valued string:
person.AccountName = "guest";

Adding custom attributes to existing objects

Since the FIM schema can be extended it is necessary to define a mechanism to allow you to add your custom attributes to the code without having to repeat the process the next time you download a newer version of the client.
For convention, you should add your own attributes in files named '{class name}_custom.cs' (the source control system is configured to ignore them).
For example, if you add a string attribute named "Account Type" to the RmPerson class, you should define a file named RmPerson_custom.cs as follows:

using System;
using System.Collections.Generic;
using Microsoft.ResourceManagement.ObjectModel;
using System.Runtime.Serialization;

namespace Microsoft.ResourceManagement.ObjectModel.ResourceTypes {
    
    // The class is defined as partial, so new attributes can be added in a separate file
    partial class RmPerson {

        // provide a getter and a setter for your attribute, check the existing code for
        // examples on how to do this according to the attribute type
        public string AccountType {
            get { return GetString(AttributeNames.AccountType); }
            set { base[AttributeNames.AccountType].Value = value; }
        }
        
        // Implement the partial method EnsureCustomAttributesExist to add your 
        // attributes to the object when it is created
        partial void EnsureCustomAttributesExist() {
            EnsureAttributeExists(AttributeNames.AccountType, false);
        }
        
        // create a static RmAttributeName object for each of your attributes.
        partial class AttributeNames {
            public static RmAttributeName AccountType = new RmAttributeName(@"AccountType");
        }
        
    }
}

The client also provides a script that generates the partial classes for you.
It is located in the code-generation folder of the client code, and you must use it like this:

# The folder where partial class files must be created
$outputDir = X:\fim-client-local\Microsoft.ResourceManagement.ObjectModel\ResourceTypes
# The address of the FIM server machine. Ignore this parameter to use localhost
$fimServer = "http://fim.foo.bar:5725"
# The credentials to use to query. Ignore this parameter to use the credentials of the currently logged in user.
$fimUser = Get-Credential
# Call the script to generate partial classes for Person and Group (if you don't specify anything, only Person is
# generated by default).
.\create-custom-resources.ps1 $outputDir $fimServer $fimUser Person,Group

The script checks which are the custom attributes by reading the bindings that have a Creator attribute set.

Last edited Apr 13, 2010 at 2:02 PM by ptedesco, version 2

Comments

rarandas Oct 6, 2010 at 11:10 PM 
It's great, very helpfully!
Could you, explain how to use that script?
Best Regards,
Rubens Arandas
www.cheetahservices.com.br