svcutil /reference and /excludeType

I get a lot of internal feedback that the svcutil options are confusing. svcutil.exe originally started out as a fairly simple tool and over the years working towards shipping it's evolved into a Swiss army knife. I figure even though I don't work on WCF anymore I should post a few brain dumps here to try and help folks out there understand things better.

/reference can have multiple meanings/behaviors depending on the what you're trying to do. A lot of thought was given to changing the parameter to make things clearer but adding yet another flag to svcutil seemed like it would be just as confusing.

In almost all modes, the /reference option can be used to help svcutil.exe locate assemblies that it might need to load. When passed an executable assembly, svcutil may also load the config file associated with that assembly (if one exists). If there are types referenced from config that are not in the GAC and svcutil needs to load and svcutil needs to load them, the assemblies may need to be provided via the /reference option.These types could be extensions, service behaviors, or service implementations in library dlls. I think of this /reference behavior as being similar to the csc.exe /lib option.

During client code generation, the /reference option can be used to avoid generating types that already exist on the client machine. svcutil will examine the assemblies passed to it for contract types (DataContract and ServiceContract but not MessageContract in v1). Whenever it encounters a type in metadata that it thinks is the same as an existing type it found it will reference the existing type instead of creating a new one. This can be useful if multiple services share the same DataContracts or implement the same ServiceContract. In this mode it's actually acting to provide svcutil with a list of existing contract types. I think of this /reference behavior as being somewhat similar to the csc.exe /reference option.

The /excludeType option complements the /reference option by allowing individual types to be excluded from  the collection svcutil loads. consider the following command line:

svcutil myServiceHost.exe /serviceName:myServiceName

Since the serviceName attribute is referring to the configuration name of the service, It's completely valid to have 2 services with the same configuration name (using the ConfigurationName property on the ServiceBehavior attribute. If this were the case, the excludeType option could be used to indicate which type should not be loaded thereby clearing up the ambiguity. Similarly, when reflecting over an assembly to generate a list of existing types, there could be 2 CLR types that represent (or seem to represent) the exact same DataContract. Again to resolve the ambiguity we can use the /excludeType option to prevent one of the types from being loaded.

/excludeType has one more use. Even without the /reference flag, the /exclude type can be used to prevent Service Contract types from being loaded. When exporting service contracts from an assembly like this:

svcutil myAssembly.dll

Ordinarily the command-line above would export all contracts in the service but the use of the /excludeType option can be used to limit the set of contracts that are exported.

I hope this explanation clears up the /reference flag a little bit. If there are any other svcutil pain points you want to me to blog about let me know.