How can I create an instance of a COM class interface as a whole?

I am trying to reorganize a piece of code and have exhausted the options that I can come up with.

This is the original code I had:

if (WebConfigSettings.ComPartition == null && HttpContext.Current != null) Nses = new NSession(); else Nses = (INSession)Marshal.BindToMoniker(string.Format("partition:{0}/new:NuntioServer.NSession", WebConfigSettings.ComPartition)); 

AND

  if (WebConfigSettings.ComPartition == null && HttpContext.Current != null) apses.Wses = new WSession(); else apses.Wses = (IWSession)Marshal.BindToMoniker(string.Format("partition:{0}/new:NuntioServer.WSession", WebConfigSettings.ComPartition)); 

And here is how I am trying to reorganize this:
(Yes, in C # you can instantiate an interface .)

  public static TInterface Get<TSubInterface, TInterface>() where TSubInterface: TInterface { <snip></snip> if (!useComPartitions) return Activator.CreateInstance<TSubInterface>(); // --> this is not cooperating return (TInterface)Marshal.BindToMoniker(.....); } 

Here is what I have already tried:

  • I tried to specify the restriction new (), and then make "new TSubInterface ()": this leads to a build error: "... there must be a non-abstract type with an open constructor without parameters in order to use it as the parameter" TSubInterface "in the generic type or method. "

  • when I use Activator.CreateInstance, I get an exception at runtime: "Unable to instantiate interface"

  • when I use Activator.CreateComInstanceFrom ("someAssemblyName", "typeName"), I get a compilation error: "Unable to convert the expression type" System.Runtime.Remoting.ObjectHandle "to return a TInterface type"

[edit] I was able to make this compiler by adding 'where is TSubInterface: class, but I'm not sure if this makes sense, since TSubInterface is an interface.
Using CreateComInstanceFrom also does not work, as it tries to find the assembly specified in the directory where this DLL is not and should not be.

Is there any way to do this compilation and run?

0
generics c # activator com
Sep 28
source share
2 answers

You need to focus on the apparent magic of creating a class object from an interface name. Let me choose an example that anyone can try. Create a new console application and use the link "Project + Add Link", "Browse" and select c: \ windows \ system32 \ shell32.dll.

Take a look at the interop library, which is created using the Object Browser. Notice how the shell type is an interface type. Now write this code:

 class Program { static void Main(string[] args) { var shl = new Shell32.Shell(); } } 

Compile and run the ildasm.exe file in the .exe file. You will see:

 .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 8 (0x8) .maxstack 1 .locals init ([0] class [Interop.Shell32]Shell32.Shell 'shl') IL_0000: nop IL_0001: newobj instance void [Interop.Shell32]Shell32.ShellClass::.ctor() IL_0006: stloc.0 IL_0007: ret } // end of method Program::Main 

Notice how the type name got replaced from Shell to ShellClass. The importer of the type library created this class, it uses the original name coclass and adds "Class" to the name. The compiler makes this replacement.

Which key, Activator.CreateInstance () cannot perform the same replacement. I don’t see an obvious way to create generics of the same lookup except using the IFooClass name instead of the interface name. Technically, you can get the [CoClass] attribute that the importer of the type library applied to the type of interface.

+3
Sep 28 '12 at 12:41
source share

This can be done by finding out what the coClass of this interface is and creates an instance of this:

 var coClassAttribute = type.GetCustomAttribute<CoClassAttribute>(); // our extension method return (TSubInterface)Activator.CreateInstance(coClassAttribute.CoClass); 

I am not happy with this, but it works. (will not mark this as the correct answer)

0
Sep 28 '12 at 12:37
source share



All Articles