如何在包装器外部使用包装资源中的类型?
How can I use types from a wrapped resource outside of the wrapper?
我正在尝试包装 COM API,以便其他人可以使用我的包装器而无需了解包装的 API。但是,我在尝试使用 COM API.
中的某些项目时遇到了问题
假设 COM API 有一个方法 returns 在 API.
中定义的对象
IComChildObject IComObject.GetChildObject()
如果我有对定义 COM API 的 dll 的引用,我可以按如下方式轻松使用它...
IComChildObject childObject = myComObjectInstance.GetChildObject();
我遇到的问题是,我需要能够通过包装器 class 使用 IComChildObject,而不引用 COM API dll。
我试图在我的包装器中创建一个接口,它可以完成这个。所以在我的包装器项目中,我有一个这样的界面。
public interface ILocalChildObject : IComChildObject{}
然后我向我的包装器添加了一个 属性,我认为这将允许我的外部代码使用 IComChildObject。
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
当我 运行 来自我的外部代码的以下代码时,ChildObject
为 null
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
我显然做错了什么,但我对此一头雾水,甚至不知道要搜索什么 Google。
也许我不清楚我想做什么,或者我想在这里做一些奇怪的事情。我想以这种方式创建一个包装器 class 库,使用它的代码不必知道有关包装库的任何信息。到目前为止,我做得很好,直到我需要在外部代码中使用包装库中的对象。我可以通过在我的外部项目中引用包装库轻松解决这个问题,但我想避免这样做。
基本上,我只需要一种在我的外部代码中使用 IComChildObject 的方法,而不需要添加对 COM API dll 的引用。
如有任何帮助,我们将不胜感激,
如果你的API是基于IDispatch you could use the 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,如果需要你可以自己重新定义接口(也许是一个简化版本)。但是运行时必须知道二进制布局才能调用它。
正如 Hans Passant 指出的那样,另一种处理方法是将 COM API 对象包装在 class 中。然后就可以通过新对象访问对象内部的属性了。这种方法的唯一缺点是需要大量输入,因为您必须重新创建要在 COM API 对象中访问的任何属性或方法。
在包装器项目中,您将创建一个 class,它将包含从 API 返回的对象。此 class 还将具有属性和方法,允许用户通过 class.
操作 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 返回的对象。然后在classChildObjectProperty
中有一个属性,它允许你获取或设置ComChildObject
的ChildObjectProperty
。
然后在我的主包装器 class 中,我可以有一个 属性 这个 returns 这个新对象(它包含 API COM 对象)。
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
然后在外部代码中我可以通过新的包装器对象对对象进行更改
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
此方法需要重新创建要通过包装器公开的所有属性和方法,但是,它允许使用包装器的用户使用 IntelliSense。
我正在尝试包装 COM API,以便其他人可以使用我的包装器而无需了解包装的 API。但是,我在尝试使用 COM API.
中的某些项目时遇到了问题假设 COM API 有一个方法 returns 在 API.
中定义的对象IComChildObject IComObject.GetChildObject()
如果我有对定义 COM API 的 dll 的引用,我可以按如下方式轻松使用它...
IComChildObject childObject = myComObjectInstance.GetChildObject();
我遇到的问题是,我需要能够通过包装器 class 使用 IComChildObject,而不引用 COM API dll。
我试图在我的包装器中创建一个接口,它可以完成这个。所以在我的包装器项目中,我有一个这样的界面。
public interface ILocalChildObject : IComChildObject{}
然后我向我的包装器添加了一个 属性,我认为这将允许我的外部代码使用 IComChildObject。
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
当我 运行 来自我的外部代码的以下代码时,ChildObject
为 null
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
我显然做错了什么,但我对此一头雾水,甚至不知道要搜索什么 Google。
也许我不清楚我想做什么,或者我想在这里做一些奇怪的事情。我想以这种方式创建一个包装器 class 库,使用它的代码不必知道有关包装库的任何信息。到目前为止,我做得很好,直到我需要在外部代码中使用包装库中的对象。我可以通过在我的外部项目中引用包装库轻松解决这个问题,但我想避免这样做。
基本上,我只需要一种在我的外部代码中使用 IComChildObject 的方法,而不需要添加对 COM API dll 的引用。
如有任何帮助,我们将不胜感激,
如果你的API是基于IDispatch you could use the 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,如果需要你可以自己重新定义接口(也许是一个简化版本)。但是运行时必须知道二进制布局才能调用它。
正如 Hans Passant 指出的那样,另一种处理方法是将 COM API 对象包装在 class 中。然后就可以通过新对象访问对象内部的属性了。这种方法的唯一缺点是需要大量输入,因为您必须重新创建要在 COM API 对象中访问的任何属性或方法。
在包装器项目中,您将创建一个 class,它将包含从 API 返回的对象。此 class 还将具有属性和方法,允许用户通过 class.
操作 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 返回的对象。然后在classChildObjectProperty
中有一个属性,它允许你获取或设置ComChildObject
的ChildObjectProperty
。
然后在我的主包装器 class 中,我可以有一个 属性 这个 returns 这个新对象(它包含 API COM 对象)。
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
然后在外部代码中我可以通过新的包装器对象对对象进行更改
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
此方法需要重新创建要通过包装器公开的所有属性和方法,但是,它允许使用包装器的用户使用 IntelliSense。