通过反射调用COM对象
来源:互联网 发布:网络拓扑发现 编辑:程序博客网 时间:2024/05/22 02:20
声明:原作者小李菜刀(caidaoli)
通过反射调用COM对象
发一篇以前写的一个旧文,申请Blog好久了,要是再不发东西可就被Kill了。
在.net中使用Com对象大家第一个反应就是在工程中引用Com对象,让vs.net自动生成一个包装过的.net类库。这种方法虽然方便,但是有很明显的缺点,最致命的就是开发的机器上安装的Com对象的版本比客户机器上安装的高,开发的程序无法正确的运行。如开发机器安装的是office 2003,而客户机器上的安装的确是office 2000、office xp甚至还有安装的是Office97,这种情况我想大家都深有体会吧?
在非托管语言如Delphi中可以通过CreateComObject来生成一个Com对象,然后再使用Variant对象去调用Com对象的属性、方法。可因C#是一种强类型的语言,他没有象Delphi中的Variant这中可变类型,因此只能通过反射去完成。
晚上心血来潮就封装了一个Variant对象来模拟一下Delphi中的Variant。
示例代码:
//生成Excel对象
using (Variant excel = Variant.CreateComInstance("Excel.Application"))
{
//显示Excel界面
excel["Visible"] = true;
//获取workBooks对象
using (Variant workBooks = Variant.CreateInstance(excel["Workbooks"]))
{
//建立一个Workbook
using (Variant workBook = Variant.CreateInstance(workBooks.InvokeMethod("Add")))
{
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
//根据指定的索引获得一个单元格
using (Variant cell = Variant.CreateInstance(excel["Cells", i, j]))
{
//设置单元格的值
cell["Value"] = i * j;
Console.WriteLine(cell["Value"]);
}
}
}
}
}
//excel.InvokeMethod("Quit");
}
using (Variant excel = Variant.CreateComInstance("Excel.Application"))
{
//显示Excel界面
excel["Visible"] = true;
//获取workBooks对象
using (Variant workBooks = Variant.CreateInstance(excel["Workbooks"]))
{
//建立一个Workbook
using (Variant workBook = Variant.CreateInstance(workBooks.InvokeMethod("Add")))
{
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
//根据指定的索引获得一个单元格
using (Variant cell = Variant.CreateInstance(excel["Cells", i, j]))
{
//设置单元格的值
cell["Value"] = i * j;
Console.WriteLine(cell["Value"]);
}
}
}
}
}
//excel.InvokeMethod("Quit");
}
这样的方式是不是爽多了?那些讨厌的可选参数终于不用再写了!
Variant类源码:
Using directives#region Using directives
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Reflection;
#endregion
class Variant : IDisposable
{
Variant() { }
object _obj;
Type _objType;
bool _isComObj = false;
public static Variant CreateComInstance(string progID)
{
Variant variant = new Variant();
variant._objType = Type.GetTypeFromProgID(progID);
variant._obj = Activator.CreateInstance(variant._objType);
variant._isComObj = true;
return variant;
}
public static Variant CreateInstance(string objectTypeName)
{
Variant variant = new Variant();
variant._objType = Type.GetType(objectTypeName);
variant._obj = Activator.CreateInstance(variant._objType);
return variant;
}
public static Variant CreateInstance(object obj)
{
Variant variant = new Variant();
variant._objType = obj.GetType();
variant._obj = obj;
variant._isComObj = obj.GetType().ToString() == "System.__ComObject";
return variant;
}
public int ReleaseComObject()
{
try
{
if (_isComObj)
return Marshal.ReleaseComObject(_obj);
else
throw new Exception("_obj is not com Object");
}
catch
{
throw;
}
}
public object InvokeMethod(string methodName,params object[] parameters)
{
try
{
return _objType.InvokeMember(methodName,
BindingFlags.InvokeMethod,
null, _obj, parameters);
}
catch
{
throw;
}
}
public object GetPropertyValue(string propertyName, params object[] parameters)
{
try
{
return _objType.InvokeMember(propertyName,
BindingFlags.GetProperty,
null, _obj, parameters);
}
catch
{
throw;
}
}
public void SetPropertyValue(string propertyName, object value, params object[] parameters)
{
if (value as DBNull != null)
value = null;
string s = value as string;
if (s != null && s.Length == 0)
value = null;
if (_isComObj)
{
try
{
object[] args = new object[parameters.Length + 1];
Array.Copy(parameters, 0, args, 1, parameters.Length);
args[0] = value;
_objType.InvokeMember(propertyName,
BindingFlags.SetProperty,
null, _obj, args);
}
catch
{
throw;
}
return;
}
PropertyInfo pi = _objType.GetProperty(propertyName);
if (pi != null)
{
if (pi.CanWrite)
{
try
{
pi.SetValue(_obj, null == value ?
null :
(pi.PropertyType.IsInterface ?
value :
Convert.ChangeType(value, pi.PropertyType)
),
parameters);
}
catch (Exception E)
{
throw new Exception(String.Format("设置属性{0}时出错!属性的类型是{1}值的类型是{2} 错误信息:{3}", pi.Name, pi.PropertyType.FullName, value.GetType().FullName, null == E.InnerException ? E.Message : E.InnerException.Message));
}
}
else
throw new Exception(pi.PropertyType.ToString());
}
else
throw new Exception(String.Format("{0}属性未在{1}中定义!", pi.Name, _obj.GetType().FullName));
}
public object this[string propertyName, params object[] parameters]
{
get { return GetPropertyValue(propertyName, parameters); }
set { SetPropertyValue(propertyName, value, parameters); }
}
IDisposable Members#region IDisposable Members
void IDisposable.Dispose()
{
if (_isComObj)
Marshal.ReleaseComObject(_obj);
}
#endregion
}
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Reflection;
#endregion
class Variant : IDisposable
{
Variant() { }
object _obj;
Type _objType;
bool _isComObj = false;
public static Variant CreateComInstance(string progID)
{
Variant variant = new Variant();
variant._objType = Type.GetTypeFromProgID(progID);
variant._obj = Activator.CreateInstance(variant._objType);
variant._isComObj = true;
return variant;
}
public static Variant CreateInstance(string objectTypeName)
{
Variant variant = new Variant();
variant._objType = Type.GetType(objectTypeName);
variant._obj = Activator.CreateInstance(variant._objType);
return variant;
}
public static Variant CreateInstance(object obj)
{
Variant variant = new Variant();
variant._objType = obj.GetType();
variant._obj = obj;
variant._isComObj = obj.GetType().ToString() == "System.__ComObject";
return variant;
}
public int ReleaseComObject()
{
try
{
if (_isComObj)
return Marshal.ReleaseComObject(_obj);
else
throw new Exception("_obj is not com Object");
}
catch
{
throw;
}
}
public object InvokeMethod(string methodName,params object[] parameters)
{
try
{
return _objType.InvokeMember(methodName,
BindingFlags.InvokeMethod,
null, _obj, parameters);
}
catch
{
throw;
}
}
public object GetPropertyValue(string propertyName, params object[] parameters)
{
try
{
return _objType.InvokeMember(propertyName,
BindingFlags.GetProperty,
null, _obj, parameters);
}
catch
{
throw;
}
}
public void SetPropertyValue(string propertyName, object value, params object[] parameters)
{
if (value as DBNull != null)
value = null;
string s = value as string;
if (s != null && s.Length == 0)
value = null;
if (_isComObj)
{
try
{
object[] args = new object[parameters.Length + 1];
Array.Copy(parameters, 0, args, 1, parameters.Length);
args[0] = value;
_objType.InvokeMember(propertyName,
BindingFlags.SetProperty,
null, _obj, args);
}
catch
{
throw;
}
return;
}
PropertyInfo pi = _objType.GetProperty(propertyName);
if (pi != null)
{
if (pi.CanWrite)
{
try
{
pi.SetValue(_obj, null == value ?
null :
(pi.PropertyType.IsInterface ?
value :
Convert.ChangeType(value, pi.PropertyType)
),
parameters);
}
catch (Exception E)
{
throw new Exception(String.Format("设置属性{0}时出错!属性的类型是{1}值的类型是{2} 错误信息:{3}", pi.Name, pi.PropertyType.FullName, value.GetType().FullName, null == E.InnerException ? E.Message : E.InnerException.Message));
}
}
else
throw new Exception(pi.PropertyType.ToString());
}
else
throw new Exception(String.Format("{0}属性未在{1}中定义!", pi.Name, _obj.GetType().FullName));
}
public object this[string propertyName, params object[] parameters]
{
get { return GetPropertyValue(propertyName, parameters); }
set { SetPropertyValue(propertyName, value, parameters); }
}
IDisposable Members#region IDisposable Members
void IDisposable.Dispose()
{
if (_isComObj)
Marshal.ReleaseComObject(_obj);
}
#endregion
}
其实Varaint类不光可以调用Com对象,对于托管对象也可以动态的创建和调用。
欢迎大家斧正!
- 通过反射调用COM对象
- 如何通过反射调用对象的方法?
- c# 对COM+对象反射调用时地址参数处理
- c# 对COM+对象反射调用时地址参数处理 c# 对COM+对象反射调用时地址参数处理
- Type通过类型调用拷贝构造函数构建对象(反射)
- Java反射:通过父类对象调用子类方法
- 通过反射调用FORM
- Golang 通过接口传递对象,并通过反射调用对象中方法
- 通过反射操作对象
- 通过反射创建对象?
- 利用反射调用COM组件
- 使用反射检查 COM 对象
- 调用 COM 对象
- ATL 调用COM对象
- 通过反射动态调用webservices
- 如何通过反射调用方法?
- 通过Java反射调用方法
- 通过Java反射调用方法
- k-means中基于密度的k值发现。
- The Game will be distributed
- TCP/IP错误,错误事件代码:10106
- 趋势分析法相关资料
- Socket在阻塞模式下的信息收发和文件接收
- 通过反射调用COM对象
- CSS之兼容浏览器篇
- asp.net 1.1的treeview 级联问题
- 可怜的鸳鸯
- c#窗口编程入门[001]--TreeView控件
- 我的迷茫
- 来玩TestRen
- VC使用CRT调试功能来检测内存泄漏
- 存储过程中调用存储过程