如何使用包装器外部的包装资源中的类型?

问题描述

我正在尝试包装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;}}
}

当我从外部代码运行以下代码时,Childobject为空

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,可以在需要时自己重新定义接口(可能是简化版本)。但是运行时必须知道二进制布局才能调用它。