Export (0) Print
Expand All

Team Development with Visual Studio .NET and Visual SourceSafe

Retired Content
This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
 

patterns & practices Developer Center

Managing Dependencies

Microsoft Corporation

January 2002

Summary: This chapter explains how you should handle assembly references, Web references, database references, and COM object references.

This is Chapter 4 of the Team Development with Visual Studio® .NET and Visual SourceSafe™ guide. Start here to get the full picture.

The information in this chapter helps you:

  • Manage dependencies and references between projects and solutions.
  • Work with dependencies on .NET assemblies, Web services, databases, serviced components, and COM Interop libraries.

You need a consistent and maintainable approach to managing dependencies in a team environment. Dependencies inevitably change over time and as a result they impact the build process (and the build order) of your application.

For example, when a dependency changes, client assemblies must be rebuilt in order to stay in step with the latest version. Depending upon the type of dependency and the way it is referenced, the Microsoft® Visual Studio® .NET build system may or may not be able to automatically handle build ordering issues.

Referencing Assemblies

When you need to use a type (such as a class or structure) contained in another assembly, you must set a reference to that assembly. This creates an assembly reference within the client assembly's manifest that identifies the name and version of the dependency. Visual Studio .NET supports two types of references: project references and file references.

Use Project References

The Projects page within the Visual Studio .NET Add Reference dialog box lists all of the other projects in the current solution. This allows you to create a project reference to another project in the same solution. Project references are the recommended way to set references because they offer many advantages.

Note   Project references are the main reason you should adopt a single solution or partitioned single solution model wherever possible.

Advantages of Project References

The advantages of using project references are:

  • They work on all development workstations where the solution and project set are loaded. This is because a project Globally Unique Identifier (GUID) is placed in the project file, which uniquely identifies the referenced project in the context of the current solution.
  • They enable the Visual Studio .NET build system to track project dependencies and determine the correct project build orders.
  • They avoid the potential for referenced assemblies to be missing on a particular computer.
  • They automatically track project configuration changes. For example, when you build using a debug configuration, any project references refer to debug assemblies generated by the referenced projects, while they refer to release assemblies in a release configuration. This means that you can automatically switch from debug to release builds across projects without having to reset references.
  • They enable Visual Studio .NET to detect and prevent circular dependencies.

Use File References Only Where Necessary

If you can't use a project reference because you need to reference an assembly outside of your current solution's project set, you must set a file reference. The following are the two ways to set a file reference:

  • To reference a .NET Framework assembly, you select the assembly from the list displayed on the .NET tab of the Add References dialog box.
  • You can use the Browse button in the Add Reference dialog box.

If you set a file reference, the path to the assembly is stored in the source controlled project file. A relative path is stored for local assemblies, while the full network path is stored for server-based assemblies, as demonstrated by the following project file snippet. Notice the HintPath attributes.

<References>
  <Reference
     Name = "System.XML"
     AssemblyName = "System.Xml"
     HintPath =   "..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3423\System.XML.dll"
  />
  <Reference
    Name = "Lib1"
    AssemblyName = "Lib1"
    HintPath = "\\BuildServer\Latest\Release\SharedComponent\SomeControl.dll"
  />
</References>
  
Note   Assemblies such as System.XML.dll are located in the Global Assembly Cache (GAC). However, you never directly refer to an assembly within the GAC. Instead, when you select an assembly on the .NET tab of the Add References dialog box, you actually reference a copy of the assembly, located within the %windir%\Microsoft.NET\Framework\<version>\ folder.

Use Copy Local = True for Project and File References

Every reference has an associated copy local attribute. Visual Studio .NET determines the initial setting of this attribute (true or false) when the reference is initially added. It is set to false if the referenced assembly is found to be in the GAC; otherwise, it is set to true.

You should not change this default setting. With copy local set to true, the Visual Studio .NET build system copies any referenced assembly (and any dependent downstream assemblies) to the client project's output folder when the reference is set.

For example, if your client project references an assembly called Lib1, and Lib1 depends on Lib2 and Lib3, then Lib1, Lib2, and Lib3 are copied to your project's local output folder automatically by Visual Studio .NET at build time.

Automated Dependency Tracking

Each time you build your local project, the build system compares the date and time of the referenced assembly file with the working copy on your development workstation. If the referenced assembly is more recent, the new version is copied to the local folder. One of the benefits of this approach is that a project reference established by a developer does not lock the assembly dynamic-link library (DLL) on the server and does not interfere in any way with the build process.

Using File References in Single and Partitioned Single Solution Systems

Use project references wherever possible and aim to minimize the use of file references.

If you adopt either the single solution or partitioned single solution model, you need to use file references only to reference outer-system assemblies (that is, those not built by your system build process). Specifically, these include:

  1. .NET Framework assemblies that are referenced on the .NET tab of the Add References dialog box. This does not present an issue within the team environment because .NET Framework assemblies are located in a common location on all development workstations.
  2. Outer system assemblies referenced by using the Browse button on the Add References dialog box. These include third-party components and assemblies built elsewhere within your company outside of your current system. For information about how to manage this type of outer system assembly, see Include Outer System Assemblies within Projects.

Using File References in Multi-Solution Systems

If you adopt a multi-solution model, this forces you to use file references on one further occasion—when you reference an assembly that is generated by a project within a separate solution.

Consider Your Reference Locations

When you are forced to reference a cross-solution assembly, you have the following two choices:

  • You can reference an assembly on the build server by using either a virtual drive letter or Universal Naming Convention (UNC) path.
  • You can copy the set of assemblies that are generated by the build process on the build server to your local development workstation and then establish a local reference with a virtual drive letter. For more information about using a virtual drive letter, please see Use a Virtual Drive for Greater Flexibility.

Advantages of Referencing Assemblies from a Build Server

The advantages of this approach are:

  • You guarantee to reference the latest version of a particular assembly as the build process updates these assemblies at regular (for example, daily) intervals.
  • The paths within your project files that contain virtual drive letters or UNC paths work across all development workstations and the build server.

Disadvantages of Referencing Assemblies from a Build Server

This approach does suffer from a couple of drawbacks which may be significant in some development environments (particularly the larger ones). The following are some disadvantages of this approach:

  • You are not in direct control of when an assembly that you reference is updated. As a result, it's possible that a new version of an assembly on the server could break your local build process at an inconvenient time when you are in the middle of developing and debugging a different area of the system. Although the central build process usually runs overnight, on occasion, interim builds need to be generated during the day. These interim builds have the potential to cause problems.
  • This approach does not support disconnected development. You are required to have a direct connection to the build server whenever you build a local project that references an assembly on the build server.

Consider an Isolated Development Approach

If you require a high level of isolation during your development work, you can adopt an isolated development approach. With this approach, you:

  1. Copy the build output from the build server to a common location on your development workstation. This can be performed manually or with the help of a script.
  2. Establish a common virtual drive (for example, drive R) so that all developers reference assemblies with the same path.
  3. Set references to the local assemblies by using the virtual drive letter (drive R).
  4. Periodically check for new build output on the build server and manually copy it locally at your convenience.

Use a Virtual Drive Letter for Greater Flexibility

If you reference a local assembly that has been copied from the build server, you should do so with a virtual drive letter established with the subst command.

Important   All developers within the team must adopt the same drive letter because it is maintained within the source controlled project file as illustrated in the following code.
<References>
  <Reference
    Name = "Lib1"
    AssemblyName = "Lib1"
    HintPath = "R:\Latest\Release\SharedComponent\SomeControl.dll"
  />
</References>
  

An additional advantage of using the virtual drive letter is that it enables you to easily remap it to different locations. For example, you may want to map it to the build server for the majority of your development time, but when you need a period of isolated development you can remap it locally.

Always Reference Release Builds with File References

The build script updates the build server on a regular (typically daily) basis with current assemblies. The build script typically generates debug and release versions of your assemblies. Developers use the debug DLLs and testers use the release DLLs, as follows:

  • As a developer, you install the debug DLLs to perform your development and unit testing work.
  • Members of the test team install a release version of the system and always test with release DLLs. Do not delay the generation of a release build until your product release date is imminent because the release build could potentially exhibit problems not present within the debug build.

To accommodate debug and release builds, the build script copies assemblies to Release and Debug folders on the build server. For detailed information, see Chapter 5, "The Build Process."

As a developer, you should always reference assemblies from the Release folder for the following reasons:

  • These ultimately represent the versions of dependent assemblies that are deployed into production.
  • You never need to change file references from the Debug folder to the Release folder in order to generate a release build. File references do not dynamically change to track configuration changes in the same way that project references do.

Use the Reference Path to Assist Isolated Development and Debugging

The one issue with referencing release assemblies is that you are unable to debug and step into the assembly. If you need to debug a referenced assembly contained within a separate solution:

  1. Copy the solution to your development workstation
  2. Rebuild a debug version of the assembly.
  3. Set the reference path within the client project to point to the debug output folder of the referenced assembly.
  4. Rebuild and run the client project. This results in the local debug version of the referenced assembly being copied to the client's project output folder. You can then debug and step into the referenced assembly.
  5. When you complete debugging and want to revert back to referencing the assembly from its usual location, remove the reference path entry.

What is the Reference Path?

The reference path is a per-computer, per-developer setting that is maintained as an Extensible Markup Language (XML) element in the project user options file (*.csproj.user or *.vbproj.user). It is used by Visual Studio .NET to help locate assembly references at build time.

Important   If you follow the guidelines presented earlier and use either project references or file references (with virtual drives) to reference assemblies, all references are directly resolved by Visual Studio .NET on any computer and the reference path will not usually be required. However, the reference path can be useful on occasion because it allows you to override the path maintained by the <HintPath> element in the source controlled project file.

Resolving Assembly References at Build Time

At build time, Visual Studio .NET resolves assembly references by searching the following locations in the following order:

  1. Look for the assembly in one of the project folders. This assumes that you have added the assembly to the project by using the Add Existing Item menu option. Project folders include any folder displayed by Solution Explorer (except when Show All Files is in effect).
  2. Look in the folders listed in the ReferencePath attribute of the <Settings> element within the project user options file. This attribute can contain a comma delimited list of folders.
  3. Use the <HintPath> element in the project file.
  4. Look in a set of folders identified by registry settings. These are the ones that contain assemblies displayed on the .NET tab of the Add references dialog box. For more details, see Using the .NET Tab of the Add Reference Dialog Box.
  5. Look for COM Interop assemblies in the obj sub folder beneath the project folder. For more details, see Referencing COM Objects.

Notice that the reference path in the project user options file takes precedence over the hint path established when you set a file reference.

Performing Isolated Development and Unit Testing

The reference path can also help you perform isolated development and unit testing within multi-solution systems. Consider solution SA and solution SB where a project within SA named PA depends upon a library project within SB called PB. If you want to perform some isolated development and unit testing on these two solutions in advance of the next system build, you can change PA's reference path to point to the output folder of PB. This allows you to make changes to PB, rebuild it locally, and then test against it in SA.

You can do this without checking in SB again and waiting for the next build process to regenerate its assemblies.

Because the reference path is a per-developer setting in the project user options file (which is not added to source control), when you next check the solutions back into VSS, you will not impact the build process or fellow developers.

How to Set the Reference Path for a Specific Project

Use the following steps to set the reference path property for a specific project.

To alter the reference path for a specific project

  1. Right-click the project within Solution Explorer, and then click Properties.
  2. Expand the Common Properties folder, and then click Reference Path.
  3. For C# projects, click the New Line icon and enter the new reference path.

    –or–

    For Visual Basic .NET project, enter the reference path into the Folder field, and then click Add Folder.

  4. Click OK to close the Properties dialog box.

Include Outer System Assemblies within Projects

The best way to handle outer system assemblies such as third-party Web controls or components that are not rebuilt by your build process is to include them directly into those projects that need to reference them. Conceptually, think of outer system assemblies the same way as .bmp or .gif files.

To include and then reference an outer-system assembly

  1. In Solution Explorer, right-click the project that needs to reference the assembly,,and then click Add Existing Item.
  2. Browse to the assembly, and then click OK. The assembly is then copied into the project folder and automatically added to VSS (assuming the project is already under source control).
  3. Use the Browse button in the Add Reference dialog box to set a file reference to assembly in the project folder.

Advantages

There are a couple of advantages to this approach:

  • Outer system assemblies remain source controlled alongside the project files. When a new version of the assembly is available, the file can be added to VSS as a new file version complete with its own file history.
  • Most importantly, your entire system is contained within VSS; this includes all outer-system assemblies, such as third party controls. You can retrieve an earlier version of the system from VSS, including all source code and external dependencies. This allows you to have a complete snapshot of the earlier system version.

Consider Sharing Outer System Assemblies in VSS

If a particular outer system assembly is referenced by multiple projects, it is maintained within every project. This makes updating the assembly to a later version a more difficult task.

You can address this issue by sharing the outer system assembly in VSS between the projects that use it. This allows the file to be updated within one project. You can refresh the copies maintained within other projects by right-clicking the project within Solution Explorer, and then clicking Get Latest Version (Recursive).

Using the .NET Tab of the Add Reference Dialog Box

The .NET tab of the Add Reference dialog box displays system assemblies and Primary Interop Assemblies that are supplied with the .NET Framework and optionally other assemblies. These are usually (but not necessarily) those installed in the GAC.

You can enable your own assemblies to appear in this list, but this requires a registry modification to designate the folder or folders that contain your assemblies.

For example, you could apply registry updates to point to the folders that contain assemblies built by your build script (either locally or on the build server). This allows developers to reference these assemblies from the .NET tab and avoids the use of the Browse button.

To add your own assemblies to the .NET tab

  1. Create a new registry key (for example, one called InnerSystemAssemblies) beneath either of the following registry keys:
    HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AssemblyFolders
    HKEY_CURRENT_USER\Software\Microsoft\.NETFramework\AssemblyFolders
      
  2. Set the new key's default value to point to the folder that contains your assemblies.
  3. If you have Visual Studio .NET open, you must close it and then launch it again for the changes to take effect.

Referencing Web Services

In single solution systems, all developers end up with local working copies of all Web services because they are defined by projects within the single solution. When you open a solution from VSS for the first time, all projects (including any Web services) are installed locally. Similarly, if a Web service is added to the solution by another developer, you install the Web service the next time you refresh your solution from VSS. In the single-solution world, there is no need to publish Web services on a central Web server within the team environment.

For Web services developed as part of a multi-solution system, not all developers need to locally install the Web service.

Within a multi-solution system, the developer of the Web service should publish the service on the central development Web server to allow other developers to access it from their client projects.

Versioning Web Services in Development

The Web services that you currently have in development will evolve over time. You should aim to keep the Web server up to date with the latest versions.

In many respects, the versioning issues associated with Web services are similar to those associated with databases. When a database schema is updated, the change must be planned and coordinated so that dependent client applications can be updated in synchronization with the schema change.

You should handle updates to Web services in a similar way. When you change the interface of a Web service, the team responsible for the service must publicize the change so that other dependent teams can update their client-side references.

Note   Implementation changes require less coordination than interface changes. However, in both cases, the team responsible for the Web service should publish change details to other developers and development teams.

Always Use Dynamic URLs

If you want to call a Web service, you must first add a Web reference to your project. This generates a proxy class through which you interact with the Web service. The proxy code initially contains a static Uniform Resource Locator (URL) for the Web service, for example http://localhost or http://SomeWebServer.

Important   For Web services in your current solution that execute on your computer, always use http://localhost rather than http://MyComputerName to ensure the reference remains valid on all computers.

The static URL that is embedded within the proxy is usually not the URL that you require in either the production or test environments. Typically, the required URL varies as your application moves from development to test to production. You have two options to address this issue:

  • You can programmatically set the Web service URL when you create an instance of the proxy class.
  • A more flexible approach that avoids a hard coded URL in the proxy, is to set the URL Behavior property of the Web service reference to dynamic. This is the preferred approach. When you set the property to dynamic, code is added to the proxy class to retrieve the Web service URL from the <appSettings> section of the application configuration file, Web.config for a Web application or SomeApp.exe.config for a Windows application.

    The dynamic URL approach also lets you provide a user configuration file, which can override the main application configuration file. This allows separate developers (and members of the test team) to temporarily redirect a Web service reference to an alternate location.

How to Use Dynamic URLs and a User Configuration File

Set the URL Behavior property of your Web service references to dynamic to gain maximum configuration flexibility both within the development and production environments. Set the production URL of the Web service in the application configuration file and provide a user configuration file for development and test purposes. The absence of the user configuration file results in the application configuration file being used.

To specify a Web Service URL in a user configuration file

  1. Add a file="user.config" attribute to the appSettings element of your main application configuration file. This silently redirects the runtime to the named user configuration file when it accesses information from the appSettings section. If the user configuration file is missing, the settings from the main application configuration file are used instead and no runtime error is generated.
    <configuration>
     <appSettings file="user.config">
       <add key="ClientApplication.SomeServer.SomeService"
            value="http://ProdWeb/myXmlWebService/Service1.asmx"/>
     </appSettings>
    </configuration>
      

    In the preceding example, ClientApplication.SomeServer.SomeService is the qualified name of the Web service proxy class. ClientApplication.SomeServer is the namespace and SomeService is the proxy class name.

  2. Create a User.config file (located in the same folder as the application configuration file), and add an appSettings entry that contains a key-value pair that identifies the Web service URL, as illustrated in the following code. Notice that in this example, the URL references the local Web server. Also notice that the <configuration> element is missing from the User.config file.
    <appSettings>
       <add key="ClientApplication.SomeServer.SomeService"
            value="http://localhost/myXmlWebService/Service1.asmx"/>
    </appSettings>
      
  3. Don't check in the User.config file to VSS. In this way, each developer (and the test team) can explicitly bind to specific URLs through their own User.config file entry. The main application configuration file should maintain the production Web service address. This is used in the absence of a User.config file.

    Tip: By default, the user configuration file is automatically added to VSS. To prevent this, right-click the file within Solution Explorer, and then click Exclude From Project. To subsequently view the file within Solution Explorer, click the Show All Files icon at the top of the Solution Explorer window.

Important   For Web applications that employ a user configuration file, any changes made to the file do not result in the Web application being automatically recycled. This only happens for the Web.config file. As a result any changes to the user configuration file are not immediately seen by the application. You must manually stop and restart the Web application. This is another reason why you should use the Web.config file for production settings and use the User.config file for only development and test settings.

Updating a Web Service Reference

To update an existing Web Service reference, in Visual Studio .NET Solution Explorer, right-click the file, and then click Update. The next time you rebuild your project, new service information in the form of a Web Services Description Language (WSDL) document is downloaded and a new local Web service proxy class is created.

Referencing Databases

Database references in the form of connection strings can also be managed by using the User.config file. The advantage of this is that each developer can easily specify his own connection string is his own private User.config file. Any changes made by one developer, such as redirecting the connection to a local database for unit testing purposes, does not affect other developers.

User configuration files can also be used to control environmental-specific settings, such as those required by a test environment. The test environment can also use a User.config file which references the test database.

The procedure is similar to the preceding Web references example, except that in that example the Web service proxy contains the code to retrieve the Web service URL from the configuration file. For database connection strings, you must provide the code to read the connection string.

How to Use User Configuration Files for Database Connection Strings

The following procedure explains how to store and then reference a database connection string within a user configuration file.

To use a user configuration file to store database connection strings

  1. Add a file="user.config" attribute to the appSettings element of your main application configuration file and include a default connection string in the main configuration file. This is used in the absence of any user-specific override.
    <configuration>
     <appSettings file="user.config">
      <add key="DBConnStr"
         value="server=PRODDB;Integrated Security=SSPI;database=Accounts"/>
     </appSettings>
    </configuration>
      
  2. To override the main application configuration file, create a User.config file (located in the same folder as the application configuration file), and then add a similar appSettings entry to the file. Notice that the following connection string references a local database.
    <appSettings>
      <add key="DBConnStr"
         value="server=(local);Integrated Security=SSPI;database=Accounts"/>
     </appSettings>
      
  3. Within your project, use the following code to obtain the connection string from the user configuration file (if it is present) or the application configuration file if it is not. This code uses the static AppSettings property of the System.Configuration.ConfigurationSettings class.
    using System.Configuration;
    private string GetDBaseConnectionString()
    {
      return ConfigurationSettings.AppSettings["DBConnStr"];
    }
    
      
      

Database Development

There are two basic approaches for database development in the team environment:

  • Central database server(s)
  • Central database servers(s) and local databases on developer workstations

Central Database Servers

The central database server or servers in the team environment mirror the production schema—or if the system is not yet in production, they reflect the most up-to-date schema. The following guidelines govern the use of database servers within the team environment:

  • Do not give developers administrative access to the database server and do not allow changes to the schema to be made by individual developers. You need to have careful control over the environment because changes made by one developer can easily impact others.
  • Grant developers specific permissions; for example, grant developers the permission to write stored procedures, functions, and (possibly) views.
  • Manage schema changes and other objects such as stored procedures with source controlled database scripts.
  • Use database scripts to ease the creation and recreation of databases.
  • Provide separate database instances for separate development efforts because configuration settings may be different for each development project.

Local Databases

The main problem with working solely against one or more central development database servers is that it is difficult to maintain a consistent set of test data. The unit testing efforts of one developer can easily impact another because test data is likely to change at frequent intervals.

As a result, it is common to install Microsoft SQL Server™ Developer Edition on each development workstation to provide an isolated test environment for each developer.

Use Database Scripts for Managing Change

You should manage all changes to the database on either the local server or on the central server through source controlled database scripts. You should provide scripts for any changes you might make manually through Enterprise Manager. You should use database scripts (that contain as much auditing and error logging as possible) to:

  • Enable a database (including stored procedures and so on) to be installed from scratch.
  • Enable a fresh set of test data to be loaded.
  • Apply updates to database schema and database objects.

Consider Visual Studio .NET Database Projects

Database scripts should be source controlled and maintained within VSS. You have two options for handling scripts:

  • Handle scripts outside of the Visual Studio .NET integrated development environment (IDE) and manually create a suitable folder structure within VSS. For example, you could create a subproject folder beneath $/Projects/SystemName called Database Objects to maintain database specific code and objects and then use separate subfolders such as Tables and Views, Diagrams and Documentation, and Stored Procedures and Functions as containers for the various object types.
  • Use Visual Studio .NET Database Projects. These are simple file based projects that allow you to store and execute database scripts, and store other information associated with your databases, such as database documentation or build files. Visual Studio .NET provides an integrated editor for Transact-SQL code, a visual Query Builder and T-SQL debugging support. The advantage of this approach is that it provides tight and automatic integration with VSS, in common with other project types.

For more information about database projects, refer to the section, "Managing Data with Database Projects within the Developing with Visual Studio .NET," of the Microsoft MSDN® Library. Also search for "Large Database Projects" within MSDN.

Referencing COM Objects

When your code calls a COM object, an Interop assembly is used to handle the type conversions between the .NET world and the COM world. When the COM object is called from managed code, a proxy within the Interop assembly is actually called. The proxy initially performs the necessary type conversion and then invokes the COM object to perform the required work.

Always Generate Compatible Interop Assemblies

In a team development environment, if you and another developer reference the same COM DLL from two different projects, the result is two Interop assemblies—one for each project.

In most circumstances, the type of the two assemblies that are created are the same, and as a result you can safely pass a reference to the COM object (via the Interop assembly) from one project to another.

To guarantee that the type of any generated Interop assembly is the same, you must ensure that the following conditions are met. Failure to do so results in a type mismatch exception at runtime when the reference is passed from one project to another even if the Interop Assembly was generated from the same COM DLL. The conditions that must be met are:

  1. All Interop assemblies must be generated from exactly the same version of the COM type library.
  2. The identity of all Interop assemblies must be the same. The assembly identity includes:
    1. The file name without extension.
    2. The public key, which may be null.
    3. The version.
    4. The culture (usually neutral for code).

The preceding conditions are generally met when you generate the Interop assembly from the Visual Studio .NET project system, by selecting the COM type library from the Add References dialog. The only exception is that it is possible (for C# projects) for the Visual Studio .NET project system to assign a strong name to Interop assemblies (the project properties dialog supports a Wrapper Assembly Key File property). In this case it is possible that two different developers could generate two Interop assemblies that are incompatible with one another.

In a team development environment, to guarantee that only one Interop assembly exists for any given version of a COM type library, you should adopt one of two approaches:

  1. Always use Primary Interop Assemblies (PIAs).
  2. If you cannot obtain a PIA, manually generate a single Interop assembly (by using tlbimp.exe) and then:
    1. Optionally assign the assembly a strong name
    2. Include it directly into those projects that need to reference it.

The following section describes both of these approaches.

Use Primary Interop Assemblies Whenever Possible

A Primary Interop Assembly (PIA) is an Interop assembly that is officially signed by the provider of the COM object and is the Interop assembly to use in all cases. If you don't have a PIA, you should request one from the provider of the COM object.

If you have a PIA, treat it like an outer-system assembly and include it directly into the project that references it. This results in the assembly being copied to the project folder. Set a file reference to the assembly in the project folder. The process is the same as the one described earlier, in Include Outer-System Assemblies within Projects.

Note   The PIAs that are supplied with the .NET Framework are located in the \Program Files\Microsoft.NET\Primary Interop Assemblies folder. When you obtain new PIAs, do not place them in this folder; if you do, you need to update all of the development workstations and build server in the team development environment. Instead, include them directly into the specific projects that need to reference them.

Use TLBIMP if you don't have a Primary Interop Assembly

If you don't have a PIA, create a single Interop assembly by using the Tlbimp.exe tool and optionally assign it a strong name. Like a PIA (and outer system assemblies), include the manually generated Interop assembly in any project that needs to reference it. This results in the assembly being copied to the local project folder from where you can reference it with a file reference.

Register COM Classes Locally

If you add an Interop assembly to a project, it does not result in the associated COM DLL being copied locally (and registered) and so you must register the COM DLL on each developer workstation. This unfortunate consequence is a result of interacting with the unmanaged world of COM.

Calling Serviced Components

A serviced component is a .NET managed class that derives from the ServicedComponent class within the System.EnterpriseServices namespace. Such classes can be hosted by COM+ applications and can use COM+ services.

In a team development environment, adopt the following recommendations when using serviced components.

Use Delayed Signing

Serviced components must have a strong name. To assign a strong name, you need a public and private key-pair that can be generated by the Sn.exe tool. In many companies, the private key is a closely guarded secret and is not available to developers on a daily basis. As a result, you should use delayed or partial signing which can be performed with only access to the public key.

The partial signing process results in a place holder being created within the assembly portable executable (PE) file for the strong name signature. The actual signing is deferred until a later stage, between system testing and product release. The build coordinator is generally responsible for finally signing assemblies.

Use Dynamic Registration

You should add the relevant assembly attributes (for example, ApplicationName, ApplicationID, and ApplicationActivation) to support dynamic registration. This allows the COM types associated with your serviced components to be automatically installed into the COM+ catalog on all development workstations, as soon as an instance of the serviced component is created.

Control the CLSID Used Within the COM+ Catalog

By default, when you rebuild an assembly it is assigned a new version number. This is because Visual Studio .NET sets the AssemblyVersion attribute to "1.0.*" for new projects. As a result, a new Class Identifier (CLSID) is generated for serviced components each time the assembly is rebuilt.

Note   This behavior is slightly different between C# and Visual Basic .NET projects. For C# projects, the assembly version is incremented every time it is rebuilt. For Visual Basic .NET projects, the assembly version is incremented the first time the project is rebuilt after it is loaded into Visual Studio .NET. Subsequent rebuilds within the same instance of Visual Studio .NET do not result in the assembly version being incremented.
This does not represent a problem, because the assembly version is for information only in assemblies that do not have a strong name. For strong named assemblies, you should use static version numbers that are manually maintained. This and other versioning issues are discussed further in Controlling Assembly Version in Chapter 5, "The Build Process".

In order to control the CLSID that serviced components end up with in the COM+ catalog and avoid multiple versions appearing each time a developer rebuilds the serviced component, use either of the following approaches:

  1. Explicitly control the CLSID by using the following Guid attribute:
     [Guid("2136360E-FEBC-475a-95B4-3DDDD586E52A")]
    public interface IFoo
    {
    }
    
    [TransactionAttribute(TransactionOption.Required),
    Guid("57F01F20-9C0C-4e63-9588-720D5D537E66")]
    public class Foo: ServicedComponent, IFoo
    {
    }
      
  2. Maintain a static assembly version number for the serviced component's assembly and don't use the Visual Studio .NET default "1.0.*" version numbering scheme. For more information about assembly versioning, see Controlling Assembly Version in Chapter 5, "The Build Process."

This is Chapter 4 of the Team Development with Visual Studio .NET and Visual SourceSafe guide. To read the next chapter, please see Chapter 5, "The Build Process."

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Show:
© 2014 Microsoft