Using Explicitly Implemented Interfaces

 

Explicitly Implemented Interfaces:

It does not appear that using explicitly implemented interfaces will allow or make easier support for generics.  VSTA does not support explicitly implemented generic interfaces such as IList<T>.

Both entry point and non-entry point types may use explicitly implemented interfaces to expose non-generic functionality without polluting the host API.  The functionality they can expose does not include the ability to pass generics or expose explicitly implement methods, properties and events (MPEs) from a generic type. 

1.       MPEs from the non-generic explicitly implemented interface can be used after casting the host type to the type of the implemented interface.  For entry point types the cast must be done on the TypeNameEntryPoint.TypeName variable since explicitly implemented interfaces are not included in the TypeNameEntryPoint types.

Functionality exposed only through casting from an add-in:

Test_Explicit_IShape testExp = this.testExp;

Test_Implicit_IShape testImp = this.testImp;

//implicitly implemented MPE's available

Color cI = testImp.Color;

//implicitly explicitly MPE's available only through casting

Color cE = ((IShape)testExp).Color;

 

2.       When explicitly implementing a non-generic interface which uses generic types, ProxyGen replaces generic types with System.Object.  Replacing System.Object with the appropriate generic type does not work because of erroneous types and canocalNames in the HTMP.

Host:

public partial class Application : IGenericTest

{

#region IGenericTest Members

   System.Collections.Generic.IList<IShape> IGenericTest.getShapes()

   {

      System.Collections.Generic.IList<IShape> list = new System.Collections.Generic.List<IShape>();

      foreach (IShape shape in this.ActiveDrawing.Shapes)

         list.Add(shape);

      return list;

   }

 

   System.Collections.Generic.IList<int> IGenericTest.getNums()

   {

      System.Collections.Generic.IList<int> list = new System.Collections.Generic.List<int>();

      for (int i = 0; i < 10; i++)

         list.Add(i);

      return list;

   }

   #endregion

}

public interface IGenericTest

{

   System.Collections.Generic.IList<IShape> getShapes();

   System.Collections.Generic.IList<int> getNums();

}

Add-in:

private void AppAddIn_Startup(object sender, EventArgs e)

{

   //null ref after return in host

   System.Collections.Generic.IList<int> ints = ((IGenericTest)this.Application).getNums();

   //invalid cast

   System.Collections.Generic.IList<IShape> shps = ((IGenericTest)this.Application).getShapes();           

}

 

3.       When explicitly implementing a generic interface ProxyGen replaces the implemented interface type with System.Object and removes all explicitly implemented MPE’s.  A seemingly possible workaround is to add these MPE’s and associated HostMemberAttributes into the proxy; however, once the metadata classes have been added an error will occur in the HTMP because the conical name passed includes the errors normally seen with generic types. 

 

Updated host type:

    public class ShapeCollection : IEnumerable, IList<IShape>

ProxyGen Output:

ProxyGen.exe Warning: 21070 : Generics are not supported. The following types contain generic parameters and will be excluded. Its occurrences will be replaced by System.Object.

    IList`1

    ICollection`1

    IEnumerable`1

    IEnumerator`1

ProxyGen.exe Information: 0 : Finished

ProxyGen.exe Information: 0 :       1 Warnings

ProxyGen.exe : ProxyGen.exe [Version 9.0.30813.0]

c Microsoft Corporation. All rights reserved.

 

ProxyGen.exe Error: 11200 : Schema validation error: The 'originalName' attribute is invalid - The value 'System.Collections.Generic.IList<Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.IShape>.IndexOf' is invalid according to its datatype 'http://schemas.microsoft.com/vsta/2008/01/ProxyGenDescriptor:name_Type' - The Pattern constraint failed.. The error occurred at line 347, position 15.

12 of the above error, one for each MPE explicitly implemented for IList<IShape>

Manually update the proxy to include the explicitly implemented interface MPEs:

#region IList<IShape> Members

 [global::Microsoft.VisualStudio.Tools.Applications.Runtime.HostMemberAttribute("System.Collections.Generic.IList<IShape>.IndexOf", BindingFlags = global::System.Reflection.BindingFlags.Instance | global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.InvokeMethod)]

int System.Collections.Generic.IList<IShape>.IndexOf(IShape item)

{throw new System.NotImplementedException();}

 

Add-In:

private void AppAddIn_Startup(object sender, EventArgs e)

{

   this.ActiveDrawing.Shapes.Add(this.AvailableShapes[0].Clone());

   IList<IShape> s = this.ActiveDrawing.Shapes;

   var x = s.Count;

}

HTMP canocalName:

Microsoft.VisualStudio.Tools.Applications.Adapter.v9.0, Microsoft.VisualStudio.Tools.Applications.DynamicProxy`1[[System.Collections.Generic.ICollection`1[[Microsoft.VisualStudio.Tools.Applications.Samples.ShapeApp.IShape, ShapeAppCSharpProxy, Version=2.3.0.0, Culture=neutral, PublicKeyToken=3c3c0c46dd27dbcf]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

 

Error:

 

 

 

 

 

 

 

 

 

 


Posted May 26 2009, 01:20 PM by BillL
Copyright Summit Software Company, 2008. All rights reserved.