Please Note that I have changed address
Go to
Baking Ways / Productive Bytes



Search This Blog

Pages

Sunday, September 12, 2010

How to quick wrap a .NET Collection in a COM component

Here is the code on how to quickly wrap up a .NET Collection and exposed it to COM so that it has a default Item property and a working For Each Loop.

These are the main changes I did to the code compared to my previous post ( see point 9 )

2) The Class NetProva inherits directly form SortedList, while before I used encapsulation and delegation to mimic inheritance. This means that we just need to code the GetEnumerator(). This is because we need this method to return the most generalized interface Collections.IEnumerator. Note the use of the new keyword in the code. We could not ovverride otherwise we would have got a System.Collections.IDictionaryEnumerator return type. Also note that we are return the Enumerator of the Keys becasue COM does not support the DictionaryEntry type.

3) The other method that we might need to implement.ovverride is the indexer. We did not need to do anything here.


TIP
You might be tempted to omit the inheritance relationship when defining a COM
interface because the base methods need to be defined anyway and you don’t have to deal with the
mess of multiply defined members. However, don’t omit the relationship because it’s
still important for proper operation on both .NET and COM sides. Not only does it
provide the expected behavior in .NET clients using such interfaces (such as implicitly
converting an INetProva type to an IEnumerable type, but for COM as well because
a CCW makes QueryInterface calls on the derived interface succeed for any of its
base interfaces.

namespace Collections01
{
// To expose properties and methods to COM, you must declare them on the class
// interface and mark them with a DispId attribute, and implement them in the class.
// The order in which the members are declared in the interface is the
// order used for the COM vtable.
// ex:
// [DispId(1)]
// void Init(string userid , string password);
// [DispId(2)]
// bool ExecuteSelectCommand(string selCommand);

//Class Interface
[Guid("2c280db5-99d0-4b5d-a014-13f6a3dfe271"),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface INetProva : IEnumerable {
[DispId(-4)] //Iterator
new IEnumerator GetEnumerator();
[DispId(2)]
void Add(object key, object value);
[DispId(3)]
int Count { get; }
[DispId(4)]
void Remove(object key);
[DispId(0)] //Default Property
object this[object key] { get; set; }

}



// To expose events from your class, you must declare them on the events
// interface and mark them with a DispId attribute.
// The class should not implement this interface.

//Events Interface
[Guid("23aaa0da-ba82-48a1-95fb-789e8e061be5"),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface INetProvaEvents
{
}



//The Class can also implement other interfaces. But only
//the first one will be exposed to COM.
//COM Class do not support inheritance beyond interface implementation
//Class Employees : List<Employee> is not COM compatible

//Class Implement the Class Interface
[Guid("4a37e6a5-2efc-42d5-91db-52787a258d85"),
ComVisible(true),
ClassInterface(ClassInterfaceType.None),
ComDefaultInterface(typeof(INetProva)),
ComSourceInterfaces(typeof(INetProvaEvents)),
ProgId("Collections01.NetProva")]
public class NetProva : SortedList, INetProva
{
public new IEnumerator GetEnumerator()
{
ICollection keys = this.Keys;
return (IEnumerator)keys.GetEnumerator();

}
}
}

No comments:

Post a Comment