Creating Proxies for Custom Exceptions

Add-in developers can catch or throw managed exceptions that are defined in the object model of your host application. However, to expose custom exceptions to add-in developers, the exceptions must meet certain requirements, and you must define some members of the proxy exceptions that ProxyGen.exe does not generate for you.

If the host application defines custom exceptions that do not meet the requirements, Visual Studio Tools for Applications automatically serializes the exceptions into a general AddInException when the host application or an add-in throws them.

Requirements for Custom Exceptions

To enable add-ins to catch or throw an exception that is defined by the host application, the exception must have the Exception class in its inheritance hierarchy, and it must be serializable. In addition, the exception can contain only the following data types in member fields:

  • Other exception types that ultimately derive from Exception.

  • A type that is defined in the host application's object model and in the proxy assembly.

  • Void.

  • Any .NET Framework type that is defined in the mscorlib.dll assembly and that has one of the following sets of characteristics:

Custom Exception Members Not Generated by ProxyGen.exe

ProxyGen.exe does not generate proxy code for exception members that are used for serialization, or for any other members that might have executable code. You must define these missing members of the generated proxy exception yourself. For more information, see Architecture of Generated Proxy Code.

The missing members that you must define include the serialization constructor (that is, the constructor that has SerializationInfo and StreamingContext parameters) and the GetObjectData method in the proxy exception. These members are required for the following reasons:

  • When the add-in catches the exception from the host application, fields in the exception will have data only if you define a serialization constructor that initializes the field values.

  • When the host application catches the exception from the add-in, fields in the exception will have data only if you override the GetObjectData method to initialize the field values.

If you do not define the serialization constructor or the GetObjectData method in the proxy exception, only the Message property will have valid data when the exception is caught by the application or an add-in.

Defining the Missing Members

You should define the missing members in a partial class that extends the generated proxy exception class, in a separate code file. This will help you avoid accidently introducing errors in the generated proxy code file. For an example that demonstrates how to do this, see Walkthrough: Creating a Proxy Assembly.

In most cases, the definitions of the missing proxy exception members will be identical to the corresponding members in the host application. However, you might need to customize the members of the proxy exception if the source or destination context for the proxy exception's serialization stream differs from the context of the exception in the host application.

The following code examples demonstrate the proxy code for a custom exception named LocationInvalidException. The first example includes the code that is automatically generated by ProxyGen.exe.

public partial class LocationInvalidException : global::System.Exception
{
    public LocationInvalidException()
    {
    }
    
    public LocationInvalidException(string message) : 
            base(message)
    {
    }
    
    public global::Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.Point invalidLocation;
}

The next example is a partial class extension that defines the members that were not generated by ProxyGen.exe. The most important aspect of this example is that it initializes the invalidLocation field in the serialization constructor and in the GetObjectData method.

[Serializable]
public partial class LocationInvalidException
{
    public LocationInvalidException(string message, Exception innerException)
        : base(message, innerException)
    { }

    public LocationInvalidException(string message, Point invalidLocation)
        : base(message)
    {
        this.invalidLocation = invalidLocation;
    }

    protected LocationInvalidException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        this.invalidLocation = (Point)info.GetValue("invalidLocation", typeof(Point));
    }

    public Point InvalidLocation
    {
        get { return invalidLocation; }
    }

     [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("invalidLocation", invalidLocation);
    }
}

Catching AddInException

If the host application or an add-in throws a custom exception that does not meet the requirements to be sent between the host application and the add-in, Visual Studio Tools for Applications automatically serializes the exception into an AddInException.

Code that catches the AddInException can determine the original exception type by using the Message property of the exception. The Message property contains the fully qualified type name of the original exception, followed by the fully qualified type names of each of the inner exceptions, and finally the text that is returned by the ToString method of the original exception.

See Also

Tasks

Walkthrough: Creating a Proxy Assembly

Concepts

Creating Proxies

Architecture of Generated Proxy Code

Reference

Proxy Generation Tool (ProxyGen.exe)