gpt4 book ai didi

c# - IReflect 和 DispId

转载 作者:行者123 更新时间:2023-11-30 22:49:36 24 4
gpt4 key购买 nike

我有一些实现 IReflect 接口(interface)的代码,用于将 IDispatch 面孔呈现到某些 .NET 对象上,而无需将所有 COM 互操作粘附到类本身。

我们使用它是因为我们有一个脚本客户端想要使用这些类,但我们不想将所有 COM 互操作内容放到类本身上。

代码大致如下所示:

[ComVisible(true)]
[ProgId("My.Factory")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
public class MyFactory
{
public object CreateObject(string type)
{
return new AutoWrap(Activator.CreateInstance(Type.GetType(type)));
}
}


[ProgId("My.AutoWrap")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
[Guid("72EAFB10-099F-4e96-A17E-B67E34DACA53")]
public class AutoWrap : IReflect
{
protected object O = null;
protected Type T = null;

public AutoWrap()
{
}

public AutoWrap(object obj)
{
O = obj;
T = O.GetType();
}

#region IReflect Members

public System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr)
{
return T.GetField(name, bindingAttr);
}

/* SNIP other IReflect methods */


public object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
// Unwrap any AutoWrap'd objects (they need to be raw if a paramater)
if (args != null && args.Length > 0)
{
for (int x = 0; x < args.Length; x++)
{
if (args[x] is AutoWrap)
{
args[x] = ((AutoWrap)args[x]).O;
}
}
}


// Invoke whatever needs be invoked!
object obj = T.InvokeMember(name, invokeAttr, binder, O, args, modifiers, culture, namedParameters);

// Wrap any return objects (that are not primative types)
if (obj != null)
{
switch (obj.GetType().ToString())
{
case "System.String":
case "System.DateTime":
case "System.Boolean":
case "System.Byte":
case "System.Char":
case "System.Decimal":
case "System.Double":
case "System.Single": // Float
case "System.Int32":
case "System.Int64": // Long
case "System.SByte":
case "System.Int16": // Short
case "System.UInt32":
case "System.UInt64":
case "System.UInt16":
break; // These Types do not get wrapped
default:
obj = new AutoWrap(obj); // Wrap Type
break;
}
}

return obj;

}

public object UnderlyingObject
{
get
{
return O;
}
}

public Type UnderlyingSystemType
{
get { return T.UnderlyingSystemType; }
}

#endregion
}

脚本客户端然后使用如下代码调用对象(VBScript 中的示例):

Set factory= CreateObject("My.Factory")
set myObject = factory.CreateObject("MyDotNetType")

myObject.DoSomething ' where DoSomething() is a method on MyDotNetType

使用上面的脚本,将创建一个包装 MyDotNetType 实例的 AutoWrap 实例,当客户端调用 DoSomething 时,InvokeMember 方法将在 AutoWrap 上调用,它转过来并在 MyDotNetType 上调用 DoSomething。

这一切在 VBScript 和 Javascript 中都运行得非常好。

但是,当尝试从 Siebel 的 eScript 脚本语言使用它时,事情会失败,因为 eScript 总是将 [DISPID=somerandomnumber] 作为名称传递给 InvokeMember,而不是像 VBScript 那样传递方法名称。

有谁知道从 .NET 代码中控制这些 DispID 的方法吗?我尝试了几种不同的方法,但都没有奏效:

  • 从其他 IReflect 成员返回自定义 PropertyInfo/MethodInfo 类,这些成员将从 GetCustomAttributes 返回 DispIdAttribute
  • 反射。在运行时发出一个包装类,它具有向 COM 公开所需的属性(我没想到这会起作用,但我想我会尝试一下)

TIA

最佳答案

我想你可以在你的字段上添加一个 [DispId(1234)] 来控制 dispid 是什么。

关于c# - IReflect 和 DispId,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1070458/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com