I'm porting a C# library to COM and I'm having a hard time trying to translate some delegates. The C# library works with some callbacks (using delegates). Usually I would translate that to events to be consumed by COM clients but the library only makes public Interfaces so I can not use the ComSourceInterfaces.
As an example of what I would like to be able to do:
[ComVisible(false)]
public delegate void ReceivedCOMMessageHandler (MessageCOM^ message);
[ComSourceInterfaces("ReceivedMessageEventInterface")]
public interface class IChannelCOM
{
bool PushMessage (MessageCOM^ message);
bool RegisterEventHandler (ReceivedCOMMessageHandler^ handler, FilterCOM^ filter);
bool UnRegisterEventHandler (ReceivedCOMMessageHandler^ handler);
property String^ Name;
event ReceivedCOMMessageHandler^ ReceivedMessage;
};
[InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
[Guid("D4D2A638-303E-41d4-8925-07A2A60B17F3")]
public interface class ReceivedMessageEventInterface
{
[DispId(1)] void ReceivedMessage(MessageCOM^ message);
};
I can't do this because the event is declared on a interface and the ComSourceInterface can only be declared in a class.
Any hints on what can I do to solve this problem?
EDIT: Another way of saying the same. Is there a way to declare events in interfaces rather than in classes in COM?
Thanks in advance.
As far as I've seen there is no way of doing that other than with Events and Events can only be thrown from a Class never from an Interface.
Related
I have been using a lot of APIs where to listen to some event I just need to implement an interface, but it doesn't require me to subscribe, how they do that?
To explain it better here is how I usually do my listeners
interface IListener
{
void OnEventHappen();
}
public class EventClass
{
public static Action onEvent;
}
public class ListenerClass : IListener
{
//constructor
public ListenerClass()
{
EventClass.onEvent += OnEventHappen;
}
//function from IListener interface
public void OnEventHappen() { //something... }
}
but in those APIs it is not necessary to subscribe anywhere, I just need to implement the interface like this: (I removed the EventClass because in those APIs I have no access to the classes who trigger the events)
interface IListener
{
void OnEventHappen();
}
public class ListenerClass : IListener
{
//function from IListener interface
public void OnEventHappen() { //something... }
}
In c# such behavior can be achieved using reflection.
One example in comments mentions Unity and it's methods like OnBeginDrag or Update. Those are not called using c# events. Unity is mostly written in c++ and after your c# code is compiled Unity looks for all classes implementing certain interfaces or inheriting from certain classes (like MonoBehaviour) and checks if they have matching methods (like Update()) so it can call them later when necessary.
Another comment mentions Photon, a networking engine commonly used with Unity. In this case there is no "magic" or even reflection. To receive Photon's callbacks you have to call PhotonNetwork.AddCallbackTarget method and pass instance of your class as an argument. Only confusing thing in case of Photon is fact, that you don't have to do that directly. Instead of calling this method yourself, you can just inherit from MonoBehaviourPunCallbacks class which implements all Photon's callback interfaces and calls PhotonNetwork.AddCallbackTarget in it's OnEnable method. That method is in turn called by Unity like I explained earlier.
I have a container WinForm called frmMain which holds another forms like frmOrder, frmMessage, the subforms was added in a TabPage control.
What I want to do is communicating between subforms, say user changes something in frmOrder and frmMessage need to be notified, currently I think the communication need to be delegated through the frmMain.
One solution I can think is to make subforms deriving from my custom Form derived class which defines interface say:
public class MessageEnabledForm: Form
{
public void SendMessage(String destFormName, String messageType, String data);
public void ReceiveMessage(String destFormName, String messageType, String data);
}
I don't know whether this is feasible, and is there any other solutions I can employ? which is generic and needn't to know the concrete subform.
Based on your question, I don't think inheritance is the best tool for the job. I say its not the best choice because you are not dealing with an "is a" relationship. I think you should consider using Events and Delegates to handle the communication between forms and subforms. The following MSDN article provides a good overview of Handling and Raising Events. You also may want to refresh yourself on the .NET INotifyPropertyChanged Interface if you using data binding in the subforms.
You could use an Interface like this, that all the child forms implement:
public interface Communication
{
public delegate void SendMessageDelegate(String destFormName, String messageType, String data);
public event SendMessageDelegate SendMessage;
public void ReceiveMessage(String destFormName, String messageType, String data);
}
When the main form receives the event, it can iterate over its "child" forms looking for a match on destFormName then call its ReceiveMessage() implementation (after casting it to the Communication interface).
I have written a COM-visible class library in C# 4.0 which I'm consuming with VB6. The thing works, only if I open up the VB6 object browser and look at the members exposed, I'm seeing an event for each and every single exposed member... but the C# code doesn't define any of them.
Is this normal? Am I doing something wrong?
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IMyClass))]
public class MyClass : IMyClass
{
public void DoSomething(string someParam)
{
...
}
}
public interface IMyClass
{
void DoSomething(string someParam);
}
The assembly is signed with a strong name key and AssemblyInfo.cs has the [assembly: ComVisible(true)] attribute set, but I'm not sure it has anything to do with the issue.
When I look at the object browser in VB6, I would be expecting to see DoSomething(string) as a member of MyClass, and I do, however I'm also seeing an event with a matching signature for every exposed method, like Event DoSomething(someParam As String) as a member of MyClass.
Even more puzzling (to me at least), properties also have a "matching" event (can only tell from the little lightning icon though) - if MyClass defined a property like this:
public string SomeProperty { get; set; }
The VB6 object browser would say the "event" is defined as Property SomeProperty As String, which leaves me flabbergasted - how does a "property" 1) gets duplicated and 2) the duplicate gets displayed with an "event" icon in the object browser? The same applies to get-only properties, which have their read-only "property/event" counterpart.
Where do these events come from and how do I get rid of them?
UPDATE An image is worth a thousand words:
UPDATE The wrong thing was the ComSourceInterfaces attribute which was mistakenly being used in place of a ComDefaultInterface attribute. Swapping the former for the latter gives the expected result:
By passing typeof(IMyClass) as an argument to the ComSourceInterface attribute you're saying that everything in the IMyClass is an event.
If you don't want an event interface for your class remove the ComSourceInterface attribute.
If you do want to expose events from your C# class to VB then do the following:
When you create a COM visible class you'll also want to create an interface that defines just the event handlers for your class. Your class should be decorated with the COMSourceInterface specifying your event handler interface and should define your events and implement the event handler interface. See How To: Raise Events Handled by a COM sink for another example.
[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface MyEvents
{
void ConnectedEvent(string state);
}
[ComSourceInterfaces(typeof(MyEvents))]
public class MyClass
{
public event Action<string> ConnectedEvent;
public MyClass() { }
public void DoSomething(string state)
{
if (ConnectedEvent != null)
ConnectedEvent(state);
}
}
See also: Murat's Corner: Exposing COM Events
You are basically finding out that there isn't anything special about events in COM. Like anything in COM, events are backed by an interface. The only thing special about an interface that specifies event methods is that it is marked with the [source] attribute in the type library. Which is all that the [ComSourceInterfaces] attribute does, recognized by Tlbexp.exe when it generates the type library.
Nor is there anything particularly special about properties in COM. They work just like they do in .NET, they are implemented with methods. A getter and a setter method.
So VB6 looks at your type library and is happy about a class that has events since it has an interface with the [source] attribute. And is happy about that interface having methods, all they can ever have, so it assumes those are the methods that run when the event is raised. It isn't otherwise smart enough to recognize that those methods are also the accessors for a property, it assumes that the type library author knows what he's doing.
Events are called "connection points" in COM. Google IConnectionPoint to learn more about it. If you ever create a WinRT component with custom event accessors then you'll also see that COM events have little in common with .NET events.
Anyhoo, the workaround is simple, only use [ComSourceInterface] when you raise events.
Does anyone knows how can I invoke method dynamically without reflection?
I`ll try to specify my question below
Suppose we have an interface IMyInterface and MyImplementation is an implementation of IMyInterface. Besides of that I have a generic proxy class MyProxy<T> where T : IMyInterface. In this proxy I wanna wrap all calls to all methods that have been defined in MyImplementation and in all inheritors of this class. The purpose I wanna achieve is the dynamic method invocation. In case of reflection everything will be transparent, but as I understand it might be quite slow. Does anyone know about solution that could be much faster?
Thanks a lot!
-- update
hmm, looks like my previous descriptions was not good, so I`ll try to describe my question again. With examples :)
So, lets imagine that we have the following code:
public interface IMyInterface
{
void Method();
}
public class MyImplementation : IMyInterface
{
public void Method()
{
Console.WriteLine("Yeaah!");
}
}
The important point that I forgot to mention is that we have a class named for example Holder. This class should be used by the following way
var holder = // the way of instantiation doesn`t really matters
holder.Register(myImplementationInstance);
var myInterfaceInstance = holder.Resolve<IMyInterface>();
myInterfaceInstance.Method();
Holder instance will return some wrapper that will implement IMyInterface and will wrap the real instance of myImplementation that has been registered.
As I said above we have a wrapper MyImplementationWrapper that implements IMyInterface and has the method named Method with the following body
public void Method()
{
_wrappedInstance.Method();
}
So, there are two questions
a) How can I automatically create the wrapper for myImplementationInstance (I dont want to know anything about object that will be registred inHolder)
b) How can I dynamically invoke the methods ofmyImplementationInstance` by its wrapper
First things first. Have you made sure that Reflection is not too slow for your needs? Do not go on hearsay - test it yourself.
Edit: To include the use of dynamic
Secondly if you are in the .net 3.5 or .net 4.0 then you can use Iron Python (or in the case of the 4.0 - any DLR language or dynamic) to do the dynamic invocation.
The DLR is a very optimal solution for this kind of thing. In C# you can use the dynamic keyword to access the dlr
I'm not sure what you're trying to achieve. It sounds, though, that what you want is a decorator, which does not require reflection.
This seems like you're trying to re-implement polymorphism...
class MyBaseImplementation
{
public virtual void MyMethod()
{
Console.WriteLine("Base");
}
}
class MyDerivedImplementation : MyBaseImplementation
{
public override void MyMethod()
{
Console.WriteLine("Derived");
}
}
static void DoSomething(MyBaseImplementation instance)
{
instance.MyMethod();
}
static void Main(string[] args)
{
MyBaseImplementation inst = new MyDerivedImplementation();
DoSomething(inst);
}
This will print "Derived", even though the parameter in the function is of type "MyBaseImplementation"
Im fully aware of the "problem" with static event handlers from a GC perspective so i'm not looking for advice on "DONT use static events" or anything like that, in my scenario this isnt a concern.
I have a static class which has an event declared
public static event EventHandler<MyEventArgs> FilePickedUpFromStorage;
i have a client service that subscribes to this event and im wanting to Mock/test the static event being fired with a fake MyEventArgs to assert the handling works as specified, at the client. Straightforwards stuff.... the problem i have is that this event is static on a static class. im looking for some solid guidance on the best approach to dealing with this, if anyone can offer any help. Changing the static event is not an option, wrapping it or any other magic is...
Thanks!
Since you specifically states that it is not an option to change the event from static to instance, you could take a look at TypeMock Isolator. It is a mocking framework that works by rewriting IL code necessary to mock stuff that could not otherwise be mocked. It is not the best solution IMO, but it will help you do want you want in this situation without changing the code.
You could keep the static event for "legacy compatibility" and provide a better structure for new (and testable) code.
// legacy
public static class OldClass
{
public static event EventHandler<MyEventArgs> FilePickedUpFromStorage;
}
// new interface for testability
public interface IBraveNewWorld
{
event EventHandler<MyEventArgs> FilePickedUpFromStorage;
}
// new implementation
public class BraveNewWorld : IBraveNewWorld
{
public event EventHandler<MyEventArgs> FilePickedUpFromStorage;
public BraveNewWorld()
{
// MyHandler forwards the event
OldClass.FilePickedUpFromStorage += MyHandler;
}
}
// new testable user of the event.
public class TestableClass
{
// here you can pass a mock or just an instance of BraveNewWorld
public TestableClass(IBraveNewWorld x)
{
}
}
You are testing your class's response to receiving an event. So presumably you are concerned about the bahviour of a method on your class which receives the event
public void OnHandler1(object sender, MyEventArgs e)
So in your tests don't you just call that method directly? You might need to mock the sender object, but presumbly he is of a known type because you're casting him to use him, so you know what to mock.
In other words for testing your class you may not actually need the real source of events at all.