.NET与COM互操作(1)-绑定与com对象创建
2010-08-26 23:53 Clingingboy 阅读(1530) 评论(0) 编辑 收藏 举报早期绑定
即定义了强类型
分两种方式
1.使用工具自动生成
1.1添加引用,则自动声明命名空间
1.2运行TlbImp命令来声明,可修改命名空间
2.手动编写,可以使用
可调用部分com接口,无需全部声明,但非常麻烦
以下为示例
1.自动声明的代码
可用实例或接口
static void CreateInstanceByWrapper() { int num0 = 6, num1 = 4; SimpleCOMCalculatorClass calcObj = new SimpleCOMCalculatorClass(); Console.WriteLine("运?算?:?{0} + {1} = {2}", num0, num1, calcObj.Add(num0, num1)); Console.WriteLine("运?算?:?{0} - {1} = {2}", num0, num1, calcObj.Subtract(num0, num1)); ISimpleCOMCalculator calcInterfaceObj = new SimpleCOMCalculatorClass(); Console.WriteLine("运?算?:?{0} * {1} = {2}", num0, num1, calcInterfaceObj.Multiply(num0, num1)); Console.WriteLine("运?算?:?{0} / {1} = {2}", num0, num1, calcInterfaceObj.Divide(num0, num1)); int factorialResult = num1; calcInterfaceObj.Factorial(ref factorialResult); Console.WriteLine("运?算?:?!{0} = {1}", num1, factorialResult); }
2.自己手动创建代码
虽然灵活,但容易出错,很麻烦,不推荐
[ComImport] [Guid("C7386CE7-47B0-43C4-82D4-5FFA7A359EEA")] public class SimpleCOMCalculatorWrapper { } [ComImport] [CoClass(typeof(SimpleCOMCalculatorWrapper))] [Guid("FB1DE569-9B3D-491F-8EFC-25478CFBF172")] public interface ISimpleCOMCalculatorWrapper { [DispId(1)] int Add(int num0, int num1); } public class CreateInstanceByCustomeWrapperClass { public static void DoTest() { SimpleCOMCalculatorWrapper obj = new SimpleCOMCalculatorWrapper(); ISimpleCOMCalculatorWrapper intf = obj as ISimpleCOMCalculatorWrapper; if (null != intf) { int result = intf.Add(1, 2); Console.WriteLine("\n用?自?定?义?包?装?类?创?建?COM对?象?。?计?算?器?:?+ 2 = {1}", obj.GetType().Name, result); } } }
后期绑定
这个很好用,采用了反射技术,无需定义任何东西就可以调用com,由于是动态的,所以性能不比前期绑定的好.
用Type的GetTypeFromProgID或GetTypeFromCLSID方法获取都可以
static void Main(string[] Args) { // 通?过?ProgID返?回?COM对?象?类?型? Type comType = Type.GetTypeFromProgID( "SampleCOMSimple.SimpleCOMCalculator.1"); // 也?可?以?通?过?CLSID返?回?COM对?象?类?型? //Guid clsid = new Guid("C7386CE7-47B0-43C4-82D4-5FFA7A359EEA"); //Type comType = Type.GetTypeFromCLSID(clsid); // 创?建?COM对?象?实?例? Object comObj = Activator.CreateInstance(comType); // 设?置?方?法?参?数? Object[] methodArgs = { 6, 4 }; // 调?用?加?法? Object result = comType.InvokeMember( "Add", BindingFlags.InvokeMethod, null, comObj, methodArgs); Console.WriteLine("运?算?:?{0} + {1} = {2}", methodArgs[0], methodArgs[1], result); // 调?用?减?法? result = comType.InvokeMember( "Subtract", BindingFlags.InvokeMethod, null, comObj, methodArgs); Console.WriteLine("运?算?:?{0} - {1} = {2}", methodArgs[0], methodArgs[1], result); // 调?用?乘?法? result = comType.InvokeMember( "Multiply", BindingFlags.InvokeMethod, null, comObj, methodArgs); Console.WriteLine("运?算?:?{0} * {1} = {2}", methodArgs[0], methodArgs[1], result); // 调?用?除?法? result = comType.InvokeMember( "Divide", BindingFlags.InvokeMethod, null, comObj, methodArgs); Console.WriteLine("运?算?:?{0} / {1} = {2}", methodArgs[0], methodArgs[1], result); // 调?用?阶?乘?方?法? // 由?于?参?数?需?要?从?方?法?中?返?回?结?果?,?要?使?用?ParameterModifier ParameterModifier paramMod = new ParameterModifier(1); paramMod[0] = true; int factorialArg = 4; Object[] methodArgs1 = { factorialArg }; result = comType.InvokeMember( "Factorial", BindingFlags.InvokeMethod, null, comObj, methodArgs1, new ParameterModifier[] { paramMod }, null, null); Console.WriteLine("运?算?:?!{0} = {1}", factorialArg, methodArgs1[0]); Console.WriteLine("\r\n按?任?意?键?退?出?..."); Console.Read(); }
p/invoke创建com对象
CoCreateInstance方法可以创建com对象,所以可以声明在托管代码中
//STDAPI CoCreateInstance( // REFCLSID rclsid, // LPUNKNOWN pUnkOuter, // DWORD dwClsContext, // REFIID riid, // LPVOID * ppv //); [DllImport("ole32.dll", ExactSpelling = true)] private static extern int CoCreateInstance( [In] ref Guid clsid, IntPtr pUnkOuter, uint context, [In] ref Guid iid, [Out] out IntPtr ppv); //HRESULT CLSIDFromProgID( // LPCOLESTR lpszProgID, // LPCLSID pclsid //); [DllImport("ole32.dll", ExactSpelling = true)] private static extern int CLSIDFromProgID( [MarshalAs(UnmanagedType.LPWStr)] string progid, ref Guid clsid);
得到指针以后然后再将其转换为托管的com接口
public static void DoTest() { Guid clsid = new Guid(); int hr = CLSIDFromProgID("SampleCOMSimple.SimpleCOMCalculator.1", ref clsid); if (0 == hr) // S_OK { Guid idispatch_id = new Guid("00020400-0000-0000-C000-000000000046"); IntPtr pIDispatch; hr = CoCreateInstance( ref clsid, IntPtr.Zero, 1, // CLSCTX_INPROC_SERVER ref idispatch_id, out pIDispatch); if (0 == hr) { object obj = Marshal.GetObjectForIUnknown(pIDispatch); if (null != obj) { ISimpleCOMCalculator intf = obj as ISimpleCOMCalculator; int result = intf.Add(1, 2); Console.WriteLine("用?PInvoke创?建?COM对?象?。?计?算?器?:?+ 2 = {1}", obj.GetType().Name, result); } } } }