I have a class implemented in C# that I want to use from a native application. The C# class has a dependency described by an interface, which is exepected to be delivered by the code instantiating the class. I would like to realize this interface in the native application and pass it to the C# object via COM. Strongly simplified, the C# code looks like this:
[ComVisible(true)]
[Guid("910E8445-7A62-403F-BAEE-17AB0C169CA8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IComWidget
{
void SetClient(IComWidgetClient client);
void DoStuff();
}
[ComVisible(true)]
[Guid("850F3EBB-CD18-4E16-881F-50B50DD5AEB0")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IComWidgetClient
{
int GetValue();
}
[ComVisible(true)]
[Guid("86B9EC33-6CDF-438F-9A67-57D009723027")]
[ClassInterface(ClassInterfaceType.None)]
public class ComWidget : IComWidget
{
private IComWidgetClient m_Client;
public void DoStuff()
{
var i = m_Client.GetValue();
Debug.WriteLine("value was {0}", i);
}
public void SetClient(IComWidgetClient client)
{
m_Client = client;
}
}
The native application loads the COM library as a side-by-side assembly with a proper manifest, and implements the IComWidgetClient interface. It seems to work, but when running automated tests on the system several tests fail with an unhandled ExecutionEngineExecption. The way it fails (the test process is aborted) smells like some kind of corruption during garbage collection.
I think I may be able to write a managed c++ unit test that mimics the steps that lead to the error. At least it fails the same way. The test looks like this:
[TestMethod]
void TestStuff()
{
IComWidgetPtr sut = NULL;
NativeClient* client = NULL;
try
{
sut = IComWidgetPtr(__uuidof(ComWidget));
client = new NativeClient();
IComWidgetClient* pvObject;
client->QueryInterface(IID_IComWidgetClient, (void**)&pvObject);
sut->SetClient(pvObject);
sut->Release();
GC::Collect();
GC::WaitForPendingFinalizers();
Assert::IsTrue(true); // If we get this far, everything went OK...
}
finally
{
sut = NULL;
delete client;
client = NULL;
}
};
Where NativeClient is a simple native object implementing IComWidgetClient
public class NativeClient: IComWidgetClient
{
...
}
What goes wrong? Is what I am trying to do at all possible?
Full source code can be found here:
https://drive.google.com/file/d/0B-D57qCpESa5MnpZUXZRN2pyNnc/view?usp=sharing
Related
I am learning Adapter pattern, and used following link to see code. Difference in my code and example code is, I removed ITarget interface, and directly created object in Client.
I know importance of using Interface, but is it really necessary to use interface, more specifically, by not creating interface, am I violating Adapter Pattern rule?
Adapter Pattern Example
My Code (without interface)
class Program
{
static void Main(string[] args)
{
Adapter obj = new Adapter();
Client client = new Client(obj);
client.MakeRequest();
}
}
public class Client
{
private Adapter _target;
public Client(Adapter target)
{
_target = target;
}
public void MakeRequest()
{
_target.MethodA();
}
}
public class Adaptee
{
public void MethodB()
{
Console.WriteLine("MethodB called");
}
}
public class Adapter
{
Adaptee _adaptee = new Adaptee();
public void MethodA()
{
_adaptee.MethodB();
}
}
Thanks.
The whole point of an adapter is that the adaptee can be used wherever a certain type is needed which is not the adaptee's type.
Assume that you have a method MyMethod(MyParameterType m). This method expects a parameter of type MyParameterType. But you don't have an object of this type. Instead you have an object that has similar functionality (maybe from a third-party library). However, this object is not of type MyParameterType, but of type MyOtherType. Of course, you can't directly pass the object to the method. That's where the adapter comes into play.
You need an object to pass to the method. Hence, it is essential that this object is of type MyParameterType; may it be an interface or class. So the Adapter has to implement or inherit this type. Otherwise, it does not make sense. You would just have another class with the same functionality as the object of type MyOtherType, but you can't use it anywhere.
Summarizing, the adapter is used to bridge architectural mismatch. This often occurs when you have several libraries that need to play together but were not supposed to do so. If you have only code that has been developed by yourself, adapters are rarely necessary because you can let the objects just implement the interface you need. This is not possible in third-party code. So you introduce adapters for that. So in the end, the adapter disguises an object to look familiar to a client, even if it is not. The interface is necessary to make it familiar. So yes, your code is not an adapter.
The problem here is you've explicitly coupled Client to the Adapter and implicitly to the behavior of how that adapter works.
Interfaces and this pattern pay off when you start using dependency injection.
Assume I have:
public Client(IAdapter target) ...
Now I can change the behavior of the adapter implementation without the Client class being changed at all:
interface IAdapter
{
void MethodA();
}
interface IAdaptee
{
void MethodB();
}
class Adapter<TAdaptee> : IAdapter where TAdaptee : IAdaptee, new()
{
private TAdaptee _adaptee;
public Adapter()
{
_adaptee = new TAdaptee();
}
public void MethodA()
{
_adaptee.MethodB();
}
}
class AdapteeA : IAdaptee
{
public void MethodB()
{
Console.WriteLine("AdapteeA");
}
}
class AdapteeB : IAdaptee
{
public void MethodB()
{
Console.WriteLine("AdapteeB");
}
}
Then with something like NInject you bind up your system:
class Program
{
private static StandardKernel _kernel;
static void Main(string[] args)
{
_kernel = new StandardKernel();
_kernel.Bind<IAdapter>().To<Adapter<AdapteeA>>();
var adapter = _kernel.Get<IAdapter>();
adapter.MethodA();
}
}
You can change your adapter and your adaptee, without client ever knowing the difference. i.e. Client is decoupled from both.
Again to make this point I can change to AdapteeB:
_kernel.Bind<IAdapter>().To<Adapter<AdapteeB>>();
It does go further too, with things like contra-variance, but that is beyond scope.
I have a problem setting up a mock, so I can call Marshal.ReleaseComObject() on my Mocked object.
I am using Moq to set up a mock of a type IFeature (from a third-party interface library). The mock setup is fairly simple:
var featureMock = new Mock<IFeature>();
IFeature feature = featureMock.Object;
In my code, The feature object is created in a while loop, running through a type of cursor (FeatureCursor). Due to legacy issues of the third-party library, the Feature object has known problems with memory leakage. Thus, I have to release the objects through Marshal.ReleaseComObject(), like shown in the code;
public class XXX
{
public void DoThis()
{
IFeatureCursor featureCursor;
//...fill the cursor with features;
IFeature feature = null;
while ((feature = featureCursor.NextFeature)!= null)
{
//Do my stuff with the feature
Marshal.ReleaseComObject(feature);
}
}
}
It works when I use real a featurecursor and features, but when when I mock the feature in a unittest, I get an error:
"System.ArgumentException : The object's type must be __ComObject or derived from __ComObject."
But how do I apply this to my Mock object?
The Mocked IFeature will just be a standard .NET class, not a COM object which is why your test is currently throwing the The object's type must be __ComObject... exception.
You just need to wrap the call to Marshal.ReleaseComObject(feature); and check whether the object is a COM object first:
if (Marshal.IsComObject(feature)
{
Marshal.ReleaseComObject(feature);
}
Then your test will work pass but won't call Marshal.ReleaseComObject (the production code will call it).
Since it sounds like you actually want to verify somehow that Marshal.ReleaseComObject was called by the code you will need to do a little more work.
Since it's a static method and doesn't actually do anything to the object itself the only option you have is to create a wrapper:
public interface IMarshal
{
void ReleaseComObject(object obj);
}
public class MarshalWrapper : IMarshal
{
public void ReleaseComObject(object obj)
{
if (Marshal.IsComObject(obj))
{
Marshal.ReleaseComObject(obj);
}
}
}
Then make your code depend on IMarshal which you can also mock in your test and verify:
public void FeaturesAreReleasedCorrectly()
{
var mockFeature = new Mock<IFeature>();
var mockMarshal = new Mock<IMarshal>();
// code which calls IFeature and IMarshal
var thing = new Thing(mockFeature.Object, mockMarshal.Object);
thing.DoThis();
// Verify that the correct number of features were released
mockMarshal.Verify(x => x.ReleaseComObject(It.IsAny<IFeature>()), Times.Exactly(5));
}
I am trying to mock the ManagementObjectSearcher class and have created a IManagementInfo interface, so how can i cast the interface to the ManagementObjectSearcher class?
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info = s as IManagementInfo;
this creates me a null info object
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info =IManagementInfo(s);
this gives me run time error (cannot typecast)
You cannot do that. Do you want to do it so that you can write unit tests? If you are trying to mock a class that you have no control of, then you have to wrap it in another class.
public class MyManagementObjectSearcherWrapper : IManagementInfo
{
public void TheMethodToMock()
{
var searcher = new ManagementObjectSearcher();
// The code you want to mock goes here
}
}
And you run your code like this:
public void YourCode(IManagementInfo info)
{
info.TheMethodToMock();
}
Then YourCode() will take either your wrapper or the mocked object. You create your mock using the IManagementInfo interface.
It looks as if you are trying to wrap a 3rd party/system object in order to aid unit testing.
Say that your starting point is
public class Dependency {
public string Foo() {
return "foo"; // machine, system, time, something else, dependent result
}
public string Bar() {
return "bar";
}
}
public class MySimpleClass {
public string MyFunc() {
return new Dependency().Foo();
}
}
[TestMethod]
public void TestSimple() {
var client = new MySimpleClass();
Assert.AreEqual("foo", client.MyFunc());
}
We are creating the Dependency inside the call because we are considering the creation cost to be less important than holding on to an instance of the Dependency. This will be dependent upon the situation. We could as easily have created a Dependency in the ctor and stored a copy which we invoked each time. Either way, we have no control over the output which makes unit testing messy.
We need to create a proxy for it.
1. Define an interface for the members that we need
Most likely, we do not need to use all of the members of the wrappee so only include in the interface those about which we care.
public interface IDependencyProxy {
string Foo();
}
2. Create a Proxy Class
We then create a proxy class wrapping the dependency and implementing interface. Again, we can create at start or on a call by call basis.
public class DependencyProxy : IDependencyProxy {
public string Foo() {
return new Dependency.Foo();
}
}
3. Define our client code in terms of the interface
We modify our client code slightly to use the IDependencyProxy interface instead of the Dependency. There are a few ways of doing this. I generally use an internal ctor which takes the dependency chained from a public ctor. (Use [InternalsVisibleTo] to allow the unit tests to see it)
public class MyRevisedClass {
private readonly IDependencyProxy dependency;
public MyRevisedClass()
: this( new DependencyProxy()) {}
internal MyRevisedClass(IDependencyProxy dependency) {
this.dependency = dependency;
}
public string MyFunc() {
return dependency.Foo();
}
}
This allows us a default behaviour for the production code (invokes the System object) and allows us to mock out the results for unit testing.
[TestMethod]
public void TestRevisedDefault() {
var client = new MyRevisedClass();
Assert.AreEqual("foo", client.MyFunc());
}
[TestMethod]
public void TestRevisedWithMockedDependency() {
var dep = new Mock<IDependencyProxy>();
dep.Setup(mk => mk.Foo()).Returns("bar");
var client = new MyRevisedClass(dep.Object);
Assert.AreEqual("bar", client.MyFunc());
}
I have implemented an IDispatch interface in C#. It in turn opens up an unmanaged COM interface which also exposes an IDispatch interface.
~MyObject()
{
Logger.TraceDebug("About to clean up object");
CleanupObject();
}
private void CleanupObject()
{
lock (lock_so)
{
try
{
if (so != null)
{
Logger.TraceWarning("Releasing object");
Marshal.FinalReleaseComObject(so);
}
}
catch (Exception e)
{
}
so = null;
}
}
The problem I'm having is that the Finalize is being called while the object is being used during normal execution meaning that attempts later to access the wrapped interface fail. When I take the cleanup code out, the code works fine but will fail when the program using the code exits (I don't have debug info from the calling app but it's likely to be the wrapped interface hasn't been disposed). I'm at a loss as to how to address this issue and thinking that my understanding is incorrect. Any suggestions would be greatly appreciated.
The object is initialised in the following:
private void InitialiseObject()
{
if (so == null)
{
so = Activator.CreateInstance(Type.GetTypeFromProgID("MyProgID));
}
}
Then used like:
public void DoSomething(string String)
{
try
{
lock (lock_so)
{
Object[] args = new Object[1];
args[0] = String;
so.GetType().InvokeMember("DoSomething", BindingFlags.InvokeMethod, null, so, args);
}
}
The point of all this is the c# interface acts as a pass through class and is able to log information being passed from the third party application to the IDispatch interface.
Why do you need this? If i ware you and i would have a dispose method to free up some resource then i would implement the IDisposable interface. Pattern
I wrote C# class to COM but I could not use it from JavaScript. Example
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICommandsEvents))]
[ProgId("Scripting.Commands")]
public class Commands : ICommands
{
public Commands()
{
}
public int CreateChannel(string channelName)
{
return 0;
}
public int GetChannelID(string channelName)
{
return CreateChannel(channelName);
}
public event ChannelEventsHandler OnChannelEvents;
}
[ComVisible(false)]
public delegate void ChannelEventsHandler(string a);
[ComVisible(true)]
[Guid("E2147768-8BA8-400b-8602-A1FDC31E6AA5")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICommands
{
[DispId(5)]
int CreateChannel(string channelName);
[DispId(6)]
int GetChannelID(string channelName);
}
[ComVisible(true)]
[Guid("22316373-A8DF-4ace-B48C-EA9953BD73FF")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ICommandsEvents
{
[DispId(1)]
void OnChannelEvents(string a);
}
and I checked "Register for COM interop" checkbox of project property.
when I want to Create this from JavaScript like this.
var a = ActiveXObject("Scripting.Commands");
I am getting "Automation Server Can't create object" exception. What is my wrong.
Thank you
There are a large number of reasons for this kind of error.
Ensure you have an assembly level GuidAttribute for the type library
First check the registry that interface, type library and coclass registration are correct.
Use Process Monitor to check the registration is being read correctly.
Attach a debugger to the process, so you can add breakpoints to your code.
Does a C# client (using COM, so you'll need to import tge typelib to create a PIA) work?
But I notice your class does not have a GuidAttribute, so coclass registration will have failed.
Make sure that your site is in 'Trusted Sites' on the client's machine.