C# 如何使用包装器之外的包装资源中的类型?
我正在尝试包装一个COM API,这样其他人就可以使用我的包装器,而不必了解包装的API。但是,我在尝试使用COM API中的一些项时遇到了一个问题 假设COM API有一个返回API中定义的对象的方法C# 如何使用包装器之外的包装资源中的类型?,c#,com,wrapper,C#,Com,Wrapper,我正在尝试包装一个COM API,这样其他人就可以使用我的包装器,而不必了解包装的API。但是,我在尝试使用COM API中的一些项时遇到了一个问题 假设COM API有一个返回API中定义的对象的方法 IComChildObject IComObject.GetChildObject() 如果我有一个对定义COM API的dll的引用,我可以很容易地如下使用它 IComChildObject childObject = myComObjectInstance.GetChildObject()
IComChildObject IComObject.GetChildObject()
如果我有一个对定义COM API的dll的引用,我可以很容易地如下使用它
IComChildObject childObject = myComObjectInstance.GetChildObject();
我的问题是,我需要能够通过包装器类使用IComChildObject,而无需引用COM API dll
我试图在我的包装器中创建一个接口,这将实现这一点。所以在我的包装器项目中,我有一个这样的接口
public interface ILocalChildObject : IComChildObject{}
然后我在包装器中添加了一个属性,我认为这将允许我的外部代码使用IComChildObject
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
当我从外部代码运行以下代码时,ChildObject
为空
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
我显然做错了什么,但我在这件事上不知所措,甚至不知道该在谷歌搜索什么
也许不清楚我想做什么,或者也许我想做一些奇怪的事情。我想以这样的方式创建一个包装类库,使用它的代码不必知道关于包装库的任何信息。到目前为止,我做得还不错,直到需要在外部代码中使用包装库中的对象为止。我可以通过引用外部项目中的包装库轻松解决这个问题,但我希望避免这样做
基本上,我只需要一种在外部代码中使用IComChildObject的方法,而无需添加对COM API dll的引用
非常感谢您的帮助,如果您的API基于,您可以使用,如下所示:
dynamic childObject = GetChildObjectSomehow();
childObject.CallAnyMethod() // compile will always succeed, will be resolved at runtime (and failed if there's like a typo error)
注:动态的
如果不是(如果它基于),则必须在外部dll或.tlb中声明此接口,或直接在C#代码中声明此接口,以便.NET运行时调用它。您不必使用原始的.dll,如果需要,您可以自己重新定义接口(可能是简化版本)。但是运行时必须知道二进制布局才能调用它。另一种处理方法,正如Hans Passant所指出的,是将COM API对象包装在一个类中。然后可以通过新对象访问对象内的属性。这种方法的唯一缺点是需要大量键入,因为您必须重新创建要在COM API对象中访问的任何属性或方法 在包装器项目中,您将创建一个类,该类将包含从API返回的对象。该类还将具有属性和方法,允许用户通过该类操作API对象
public class LocalChildObject
{
internal IComChildObject ComChildObject;
public string ChildObjectProperty { get { reutrn ComChildObject.ChildObjectProperty; } set { ComChildObject.ChildObjectProperty = value ;}}
public LocalChildObject(IComChildObject ComChildObject)
{
this.ComChildObject = ComChildObject;
}
}
在本例中,ComChildObject
是从API返回的对象。然后类ChildObjectProperty
中有一个属性,它允许您获取或设置ComChildObject
的ChildObjectProperty
然后在我的主包装器类中,我可以有一个属性返回这个新对象(它包含API COM对象)
然后在外部代码中,我可以通过新的包装器对象对对象进行更改
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
此方法需要重新创建要通过包装器公开的所有属性和方法,但是,它允许使用包装器的用户使用IntelliSense。如果您的API基于IDispatch,则可以使用
dynamic
关键字(尚未在.NET core上)或键入.Invoke(“名称”)。如果不是(如果它基于IUnknown),则必须在外部dll或.tlb中声明此接口,或直接在C#代码中声明此接口,以便.NET运行时调用它。@SimonMourier感谢您的帮助。我如何知道API是基于什么的?我不能控制API,我只能通过COM访问它。我唯一可以更改的代码是包装器代码,以及使用包装器的代码。@SimonMourier谢谢您的帮助。我使用了dynamic,它很有效。如果您将注释转换为答案,我将接受它作为正确答案。接口不是包装器,不会隔离互操作程序集引用。你需要上课。假设ChildWrapper具有IComChildObject类型的私有字段。就像你对ComWrapper做的一样。这确实会让人感到无聊,当您看到自己不得不用一行代码复制所有子对象属性和方法时,您会开始想,这有什么意义。倾向于了解更多关于您包装的库的信息,但这不起作用。这似乎是最简单的解决方案。但是,它不允许包装器的使用者使用IntelliSense查看对象的方法和属性。目前这可能是可以接受的,但我将继续寻找一种解决方案,使他们能够更轻松地创建代码。再次感谢我们的帮助。@Tim-若要使用intellisense作为COM对象,这意味着您必须以某种方式使用.tlb。你的COM API有一个.tlb吗?您可能会这样做,因为当您使用.dll时,intellisense正在工作。在这种情况下,您可以只导出.tlb和.NET用户可以引用它而不是.dll。它们将只包含元数据,而不包含代码。
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";