Customizing generated partial contract classes

Nov 23, 2009 at 5:53 PM

Hi, I've been evaluating WSCF.Blue for generating server stubs from WSDL and I'm really impressed so far.  So thanks! 

For the service operation I'm having a partial class generated and then implementing the call to [OperationName]Implementation in another partial class, good to go, I don't have to change the generated code.  However, I've got a question about the partial classes that are generated for the contracts.  Since customizations through overrides are not available with partial classes, how can the implementation of the data and message contracts be customized?  For example, my response message has an AssemblyVersion property, and I'd like to have the corresponding response message class populate via reflection, but how, without changing the generated code?  I know I can create additional properties via a new partial class, but then I'm changing the contract interface, not just the implementation.  So how are others making use of generated contract classes marked as partial?

Instead of generating traditional get;set; from private variables would it be feasible to provide call through methods that could be implemented in partial classes?  So, something like this...?

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="token", Order=5, ElementName="Version")]
public string Version
{
    get
    {
        return VersionGetter();
    }
    set
    {
        VersionSetter(value);
    }
}

 That could then be implemented in separate partial as...

private string VersionGetter()
{
    return Assembly.GetExecutingAssembly().GetName().Version.Major.ToString();
}

private void VersionSetter(string value)
{
    // do nothing, value is readonly
}

I don't know if this is a good idea though, it'd be a load of work to have to provide getter/setter functions for every property, unless those were also generated, but then I'm back to editing generated code.  Tell me I'm just missing something obvious.

Thanks!

Nov 23, 2009 at 6:25 PM
Edited Nov 23, 2009 at 6:26 PM

Partial properties would be an option, but aren't support.  Perhaps generating partial methods inside the property setter/getter would help.  An On[Property]Get that would allow modifying the private var before returning it, and an On[Property]Set that would allow modifying the private var after it was set...

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "token", Order = 5, ElementName = "Version")]
public string Version
{
    get
    {
        OnVersionGet();
        return this.versionField;
    }
    set
    {
        this.versionField = value;
        OnVersionSet();
    }
}

partial void OnVersionSet();
partial void OnVersionGet();

Then you'd have to provide additional partial implementations for only what needs customization, all other properties would operate unchanged.

partial void OnVersionGet()
{
    this.versionField = Assembly.GetExecutingAssembly().GetName().Version.Major.ToString();
}
Developer
Nov 24, 2009 at 10:03 AM
Edited Nov 24, 2009 at 10:08 AM

Hi Joel,

I personally always treat the data contract types like simple Data Transfer Objects, and have the service implementation set the required values on the instance before it is returned. This helps to keep all business logic centralised in the one place.

In your example you could still use reflection to get the assembly that contains the type and manually set the property:

foo.Version = Assembly.GetAssembly(typeof(Foo)).GetName().Version.Major.ToString();

That said, I have no issue with adding extensibility points, and partial classes and methods were certainly designed to achieve that very goal for generated code. I will add a work item for making hooks available for the property accessors in the data contract types. I would probably pass the field into the partial method (by reference to cater for value types) so that the implementer didn't have to reference a field that isn't defined in their partial class. Something like this:

partial void OnPropertyGet(ref bool propertyField);
partial void OnPropertySet(ref bool propertyField);

Cheers,

Alex.

 

Developer
Nov 24, 2009 at 10:06 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.