问题描述
我正在尝试包装COM API,以便其他人可以使用我的包装,而无需了解有关包装API的任何信息。但是,尝试使用COM API中的某些项目时遇到了问题。
比方说,COM API具有一种返回API中定义的对象的方法。
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;}}
}
ILocalChildobject Childobject = myComWrapper.ComChildobject;
我显然做错了事,但是我对此深有感触,甚至不知道该搜索什么。
也许我不清楚我要做什么,或者我想在这里做一些奇怪的事情。我想以这种方式创建包装器类库,从而使使用该包装器类的代码不必了解有关包装器库的任何知识。到目前为止,我做得还不错,直到需要使用外部代码中的包装库中的对象为止。我可以通过引用外部项目中的包装库来轻松解决此问题,但我想避免这样做。
基本上,我只需要一种在外部代码中使用IComChildobject的方法,而无需添加对COM API 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
中有一个属性,该属性使您可以获取或设置ChildObjectProperty
中的ComChildObject
。
然后在我的主包装器类中,我可以有一个属性,该属性返回此新对象(包含API COM对象)。
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
然后在外部代码中,我可以通过新的包装器对象对对象进行更改
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
此方法需要重新创建要通过包装公开的所有属性和方法,但是,它确实允许使用包装的用户使用IntelliSense。
,如果您的API基于IDispatch,则可以使用dynamic keyword,如下所示:
dynamic childObject = GetChildObjectSomehow();
childObject.CallAnyMethod() // compile will always succeed,will be resolved at runtime (and failed if there's like a typo error)
注释动态为not available on .NET core for COM objects yet。
如果不是(如果它基于IUnknown),则必须在外部dll或.tlb中或直接在C#代码中声明此接口,以便可以由.NET运行时。您不必使用原始的.dll,可以在需要时自己重新定义接口(可能是简化版本)。但是运行时必须知道二进制布局才能调用它。