Adapter and proxy issues

Q:

I’m using ShapeAppBasicCSharp sample.

I'm pretty clear on using Adapters to pass types that are not in VSTA proxy.  Not clear on how to mix a proxied type with a custom adapter type.

In this sample,I’ll start simply by passing the current Document as IElement through custom adapter:

Add new type with DocElement property off Application. 

    public partial class Application . . .

        public ShapeAppCSharp.Contracts.IElementContract DocElement

        {

            get

            {

                return this.document as ShapeAppCSharp.Contracts.IElementContract;

            }

        }

 

Document implements IElementContract

    public sealed class Document : ShapeAppCSharp.Contracts.IElementContract //ShapeAppCSharp.IElement

    {

. . .

       #region IElementContract Members

        private string elementID;

        public string ElementID

        {

            get

            {

                if (String.IsNullOrEmpty(elementID))

                {

                    Guid guid = Guid.NewGuid();

                    elementID = guid.ToString();

                }

                return elementID;

            }

        }

        #endregion

 

Add-In calls API:

        private void AppAddIn_Startup(object sender, EventArgs e)

        {

            //serializationexception -- Document does not serialize, add ShapeAppCSharp.IElement to ShapeAppCSharpProxy?

            ShapeAppCSharp.Contracts.IElementContract docElement = this.DocElement;

            string id = DocElement.ElementID;

// normal API

            Document doc = this.Document;

            id = doc.ElementID;

        }

 

Type is expected to resolve, but throws serialization exception (Document as ObjectToPack does not serialize).

This occurs after assigning e.ObjectToPack (Document instance) to e.AdapterToReturn  as ShapeAppCSharp.Contracts.IElementContract:

in ShapeAppCSharp.HostSideAdapters

[System.AddIn.Pipeline.HostAdapterAttribute()]

public class IShapeAppEntryPointContractToViewHostAdapter

 

       void TypeInfrastructureManager_AdapterResolve(object sender, AdapterResolveEventArgs e)

        {

            if (typeof(ShapeAppCSharp.Contracts.IElementContract).IsAssignableFrom(e.ExpectedType))

            {

                e.AdapterToReturn = e.ObjectToPack as ShapeAppCSharp.Contracts.IElementContract;

            }

        }

 

Any suggestions?

 

A:

It looks like public sealed class Document is effectively acting as an adapter in this case in that case for contract to be marshalable across the boundary you need to have the adapter type derive from MBRO.

 

Q

Yes, that helped shed some light. 

I was confused by the proxied Document class def, (which is MBRO):

public abstract partial class Document : global::System.MarshalByRefObject

Now The Document's IContract impl is called:

        public System.AddIn.Contract.IContract QueryContract(string contractIdentifier)

        {

            return this;

        }

 

But, on the way out of  proxy's ApplicationEntryPoint Document property

public partial class ApplicationEntryPoint : global::ShapeAppCSharp.IShapeAppEntryPoint

       public virtual global::Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.Document Document

        {

 

            get { return ((global::Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.Application)(remoteObject)).Document; }

        }

I hit a new exception:

System.InvalidCastException {"Unable to cast transparent proxy to type 'Microsoft.VisualStudio.Tools.Applications.Contract.IInteropObjectContract2'."}

 

A:

Return of null should be done in the QueryContract instead of returning this for every contract identifier. In this case when trying to get object from contract the runtime checks if it implements IInteropObjectContract2 it gets a not null value assuming it got an implementation it tries the cast.

So only return a not null value if you recognize the contractIdentifier. Also in this case it would be better if you create a new adapter otherwise you would have versioning issues with document type that is acting as a adapter now. In the new adapter you could derive it from ContractBase and that should take care of QueryContract requests. Also this you would refrain the object model of knowing contract details.

 

 

 


Posted May 22 2009, 02:40 PM by BillL
Filed under: , ,
Copyright Summit Software Company, 2008. All rights reserved.