-
using System;
-
using System.Collections.Generic;
-
using System.Text;
-
using System.Runtime.InteropServices;
-
-
namespace ClassLibrary5
-
{
-
[Guid("99999999999A-CCCCc-ADDD-73444444E530")]
-
public interface IVehicle
-
{
-
bool Start();
-
bool Stop();
-
string VehicleName { get; set; }
-
string VehicleType { get; set; }
-
}
-
-
[Guid("4444444444444-1111-5555-44464445FF9")]
-
[ClassInterface(ClassInterfaceType.None)]
-
public abstract class Vehicle : ClassLibrary5.IVehicle
-
{
-
private string _VehicleName;
-
private string _VehicleType;
-
-
public string VehicleName
-
{
-
get
-
{
-
return _VehicleName;
-
}
-
set
-
{
-
_VehicleName = value;
-
}
-
}
-
-
public string VehicleType
-
{
-
get
-
{
-
return _VehicleType;
-
}
-
set
-
{
-
_VehicleType = value;
-
}
-
}
-
-
public abstract bool Start();
-
public abstract bool Stop();
-
-
-
}
-
}
COM Interop: Base class properties not exposed to COM
-
Thursday, October 04, 2007 8:44 AMHi,
I have a C# Class Libarary which is exposed to COM. The issue is base class members are not exposed to COM.As per msdn
http://msdn2.microsoft.com/en-us/library/8877bdk6(VS.80).aspx Managed Clas hierarchies flatten out when exposed as COM objects.
Please let me know how i can resove this issue. Thanks a lot in advance
Here is the sample Application Code:
The issue is base class member properties VehicleName ,Vehicle Type are not exposed to COM
Base Class:
Derived class:
Code: ( text )Thanks,-
using System;
-
using System.Collections.Generic;
-
using System.Text;
-
using System.Runtime.InteropServices;
-
-
namespace ClassLibrary5
-
{
-
[Guid("00000000000-7771-8888-F8487777988")]
-
public interface ICar : IVehicle
-
{
-
string CarType { get; set; }
-
int ModelNumber { get; set; }
-
bool Start();
-
bool Stop();
-
}
-
-
[Guid("111111111-1234-1234-4567-C5077F131")]
-
[ClassInterface(ClassInterfaceType.None)]
-
public class Car : Vehicle, IVehicle, ICar
-
{
-
private int _ModelNumber;
-
private string _CarType;
-
-
public int ModelNumber
-
{
-
get
-
{
-
return _ModelNumber;
-
}
-
set
-
{
-
_ModelNumber = value;
-
}
-
}
-
-
public string CarType
-
{
-
get
-
{
-
return _CarType;
-
}
-
set
-
{
-
_CarType = value;
-
}
-
}
-
-
public override bool Start()
-
{
-
//Start code goes here
-
return true;
-
}
-
public override bool Stop()
-
{
-
//stop code goes here
-
return true;
-
}
-
}
-
}
-
All Replies
-
Thursday, October 04, 2007 2:14 PMModerator
You are being misled by the documentation. If you allow the compiler to auto-generate the COM visible interface for you then it will flatten out the members when it builds the COM interface. COM only works through interfaces so the interface determines what COM sees. In your case you defined the COM visible interface. Therefore COM clients can only see the members that your COM visible interface defined. This applies to any member of your class whether it is defined within the class or inherited. For example:
[ComVisible(true)]
[Guid(...)]
public interface IFoo{
public void Bar ( );
}[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
[Guid(...)]
public class MyFoo : IFoo
{
public void Bar ( ) { } //Visible to COM
public void Bar2 ( ) { } //Not visible to COM
}By using ClassInterface you are telling COM that you are going to determine what is (and is not) exposed to COM. This is the proper way (IMO) to do COM interop as it avoid exposing unneeded members. You can, of course, add the inherited members to your COM interface and they will get exposed to COM clients and your base class will continue to implement them.
[ComVisible(true)]
[Guid(...)]
public interface IFoo{
public void Bar ( );
public void Bar2 ( );
}public abstract class MyFoo : IFoo
{
public void Bar ( ) { } //Visible to COM
}
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
[Guid(...)]
public class MyFoo2 : MyFoo
{public void Bar2 () { } //Visible to COM
}Michael Taylor - 10/4/07
-
Thursday, October 04, 2007 3:28 PM
Hi Michael,
Thanks a lot for your quick response and explanation of what needs to be done.
As per your clarifications, i understand that we need to add the base class properties to the derived class interface to make it exposed to com.
Please consider the following points/questions:
1) In the below example eventhough the ICar interface inherits from IVechicle interface why do we need to add the base class properties to ICar interface?
2) I have some 10 derived classe which is inherited from the the same base class, do i need to add the all the base class properties to all
the 10 derived class interfaces to make the properties visible?//Base class Vehicle has two properties vehicleName and vehicleType
public class Vehicle//Base class
{
int vehicleName;
int vehicleType;
public VehcileName //Not exposed to COM
{
get{}
set{}
}
public VehcileType //Not exposed to COM
{
get{}
set{}
}
public int start()
public int stop()
}//Derived class inherits Vehicle
public class Car:Vehicle,ICar //inherits vehicle class
{
public int carType
public int CarNumber
public int start()
public int stop()
}//Derived class inherits Vehicle
public class Bus : Vehicle,IBus //inherits vehicle class
{
int busType
int NumberofSeats
int start()
int stop()
}//Base class interface
public interface IVehicle
{
public VehcileName{get;set;}
public VehcileType{get;set;}
}
public int start()
public int stop()
}//Car Interface which inherits from IVehicle
public interface ICar:IVehicle //inherits IVehicle
{
int carType
int carNumber
int vehcileType//base class properties added to derived class as this is not exposed
int VehcileName//base class properties added to derived class as this is not exposed
}
Thanks a lot in advance for you kind help. -
Thursday, October 04, 2007 3:56 PMModerator
Just so we're clear on everything to this point let me lay out a few "rules" that are followed for COM.
-
COM only deals with interfaces. Base/derived classes have no meaning or functionality in COM. Inheritance is not applicable either.
-
In COM interfaces can inherit from one another. However the .NET implementation that exposes the .NET interface to COM does not support inheritance. Therefore you must replicate any interface members in a base interface to the derived interface.
-
Moving members between a base and derived class will have no impact on what is visible to COM.
-
When you explicitly define a COM interface to be exposed (like I recommend and how you've done) then you are completely responsible for determing what does and does not get exposed to COM. The compiler will not use reflection or anything else to determine what should be exposed.
-
All COM classes have a single, default interface. This is the interface that is normally used for an object. A COM class can expose other interfaces but the COM client must then query for the interface. In .NET the first COM-visible interface is used as the default interface for a COM class. The ordering changed between v1.x and v2.
For the following discussions I'm going to leave off the various attributes that are normally applied. To clarify point 2 imagine the following:
Code Blockpublic interface IFoo
{
public void FooMethod();
}public interface IFoo2 : IFoo
{
public void FooMethodEx();
}public class FooClass : IFoo2
{
public void FooMethod ( ) { }
public void FooMethodEx ( ) { }
}Because of how the .NET interop works only the IFoo2 explicit members are visible in COM. The interop code does not look at base interface types when building the exposed COM interface. Therefore IFoo2 must also include all members of IFoo when defining the interface. This is one of the big reasons why you should isolate your COM-visible types from .NET types. If you try to do this:
Code Blockpublic interface IFoo2 : IFoo
{public void FooMethodEx ( );
//IFoo members
public void FooMethod ( );
}Then now COM will see the IFoo and IFoo2 members but .NET will get ambiguity errors because FooMethod is defined in two different interfaces. The additional problem though is that if the COM client queries for IFoo then it'll fail because FooClass only implements IFoo2 as far as COM is concerned. The most practical approach is to define each COM interface separately (without inheritance) and then have the COM class implement each of the interfaces explicitly.
Note that the above only applies to COM interfaces that you define within .NET and expose to the outside world. If you are implementing a COM interface in .NET that was defined in unmanaged code (say IShellView2) then you won't be reregistering the COM interface so the unmanaged inheritance will work for it. You still have to break up the interface in the .NET code but the COM client will work correctly (at least I believe so, you'd have to try it to verify).
On point 5, in v2 the basic rule is that the first COM-visible interface found in a class'es inheritance list is used as the default interface. If you derive from a base class that also has a COM visible interface then the rules get messier. I think it still defaults to the derived-class'es first visible interface but I'm not 100% sure. There is a new attribute that you can apply to a COM class to explicitly identify the default interface. If you have a base class and COM visible interface on the same type then consider using the attribute to avoid confusion.
Now on to your question. Remember that COM is interface based. Whether you implement the interface member in a base or derived class is irrelevant so we'll move away from the entire base/derived class discussion. Instead focus on how the interfaces are defined.
Assuming that IVehicle and ICar are COM visible then you must replicate the members of IVehicle in ICar in order for COM to see the vehicle members in ICar (as you have done). The .NET interop does not support interface inheritance of COM interfaces.
As for the base/derived classes it doesn't matter where you implement the interface members. You can implement some in a base class and some in derived if you want. Here is an example:
Code Blockpublic interface IVehicle //COM visible
{
public int VehicleType { get; }public string VehicleName { get; set; }
}public interface ICar //: IVehicle - COM visible
{
public int CarType { get; set; }//IVehicle
public int VehicleType { get; }
public string VehicleName { get; set; }
}public abstract class VehicleBase : IVehicle //Not COM visible since it can't be created
{public virtual int VehicleType { get ; set; }
public virtual string VehicleName { get; set; }
}public class Car : VehicleBase, ICar, IVehicle //COM Visible
{
//ICar members
//IVehicle members
}A few notes. Since I believe in segregating COM visible stuff from .NET stuff (so you can remove it later) I would not be using any of COM visible interfaces in .NET code. As a result I throw out most .NET guidelines as far as design goes. In the above code I could have used inheritance but, since COM won't see it, there is no benefit.
Next note. Car derives from VehicleBase so I get the default impl of IVehicle. However so that COM clients can query for either ICar or IVehicle I have to include these interfaces in my inheritance list. COM clients will see the Car class as implementing both interfaces even though, internally, I had to replicate the members. Some of the interface members are implemented in the derived class while others are implemented in the base class.
Final note. Explicit interface implementations, rather than public, are a good choice here to keep the .NET member list clean. .NET clients don't care about the ICar, IVehicle stuff so don't bother showing it to them.
Michael Taylor - 10/4/07
-
-
Thursday, October 04, 2007 5:03 PM
Hi Michael,
Thanks a lot for your valuable time and detailed explanation of COM Interfaces.
I will try to implement the stuff you have mentioned. Also let me know what other steps do you follow for segregating COM visible stuff from .NET stuff.
Please let me know the links where i can find more documention on these topics.
Thanks,
-
Thursday, October 04, 2007 5:13 PMModerator
The best place to learn about COM interop is at MSDN: http://msdn2.microsoft.com/en-us/library/zsfww439(vs.80).aspx It covers most of the information you'll need.
Michael Taylor - 10/4/07
-
Saturday, October 06, 2007 10:09 AMHi Michael,
I have futher questions regarding ComInterop
1) Exposing enumerations to COM
Following enum is exposed to com
Code BlockGuid(""),ComVisible(true)]
public enum Colors{ RED= 0, BLUE= 1, TWO = 2, THREE = 3, FOUR = 4 }- The issue is when i use the enum colors in the Com the enum members are prefixed with enum name as Colors_RED, Colors_BLUE any idea on why enum name is prefixed to its members?
- To make the enum comvisible adding Guid is just enough or is there any other steps that i need to follow?
If i have an overloaded method Add then it will be exposed to com as Add, Add_1, and Add_2is there any solution to overcome this (MSDN http://msdn2.microsoft.com/en-us/library/8877bdk6(VS.80).aspx suggests to have different names but in my case i cant have different names)
3) What is the the best design guidline: Setting the ComVisible attribute of entire asembly to true and turnoff the
attribute when it is not required v/s turning of the comvisible atrribute at assembly level and turning it on when ever required.
Thanks a lot in advance, -
Saturday, October 06, 2007 3:10 PMModerator
1) The enumeration is correct. Unlike C#, languages that support enumerations often require them to be globally unique (like early versions of C++). Therefore the exporter prefixes each enumeration member with the name of the enumerated type. You can see this same behavior if you browse through the framework enumerations that were exposed to COM.
2) Most languages do not support overloading. COM does not support it at all. Each exposed member of an interface must have a unique name. Therefore the exporter converts the other overloads to unique names. There is no workaround for this as COM doesn't support overloading.
The attribute ComAliasName can be used to rename certain aspects of COM-visible types but I don't know if it will work in this case. You could try applying it to the enumeration members. For the overloads you can try it as well but you can't reuse an existing name so the names still have to be unique.
Michael Taylor - 10/6/07
-
Sunday, October 07, 2007 6:14 AM
Hi Michael,
Thanks a lot for all help.
Thanks and Regards, -
Tuesday, January 24, 2012 10:16 PM
Hello all.
I am a newbie to .Net but trying to use VS 2010 and .Net to generate a web client proxy for use by a unmanaged code via COM. VS 2010 has the ability to generate the client proxy classes via use of the WSDL definition (and apparently using the WSDL.exe program). I did not have to code a line. I set the flag to allow com visible and built the result.
Generally this will work OK from unmanaged code as long as you do not need to send parms in the SOAP header. Unfortunately I do. the classes are generated just fine. Unfortunately the classes generated inherit form other classes. From my reading that is the cause of my problems.
I have read that one solution is somehow to make them visible to com. Believe me I have read and reread this thread and many others and so far have not figured out how to do this. Hopefully it is quite straightforward and someone will take pity on me and show me the light.
Bob
Bob Alston -
Friday, January 27, 2012 12:45 PMcommon language runtime (CLR) that makes it an extremely powerful platform is that it allows seamless interactions between managed applications and unmanaged COM components. All COM classes have a single, default interface Reallocating members between a base and derived class will have no impact on what is visible to COM

