我认为这是一个工厂/提供商类型的故事,但我不确定如何描述我的问题。事情是这样的。
InstallShield 有一个 COM 自动化接口,他们在每个版本中都会更改它的名称。如果是 VBScript,我会说,
set project = CreateObject("ISWiAuto15.ISWiProject) ' InstallShield 2009
set project = CreateObject("ISWiAuto16.ISWiProject) ' InstallShield 2010
一旦我有了一个项目对象,我就可以做类似的事情,
project.OpenProject( filePath, readOnly )
在 C# .NET 3.5 中,我添加 COM 引用并执行相同的操作,只是现在我与该类紧密耦合。我希望能够做类似的事情
var project = CreateProjectObject( typeof ISWiAutoXX.ISWiProject )
,但我不知道如何做到这一点,因为似乎没有任何共享接口可以使用。
我运气不好还是有办法处理此类问题?
I think this is a factory / provider type story but I'm not sure how to describe my problem. It goes like this.
InstallShield has a COM Automation Interface that they change the name of it with each release. If it was VBScript I'd say
set project = CreateObject("ISWiAuto15.ISWiProject) ' InstallShield 2009
set project = CreateObject("ISWiAuto16.ISWiProject) ' InstallShield 2010
once I have a project object I can do things like
project.OpenProject( filePath, readOnly )
In C# .NET 3.5 I add my COM reference and do the same things except now I'm tightly coupled to that class. I want to be able to do something like
var project = CreateProjectObject( typeof ISWiAutoXX.ISWiProject )
But I can't figure out how to do this as there doesn't seem to be any shared interface to cast with.
Am I out of luck or is there a way to handle this type of a problem?
发布评论
评论(5)
如果您仅使用 .NET 3.5,最好的选择可能是编写自己的接口来公开所需的确切功能,然后使用 IS 2009 和 IS 2010 实现接口。这允许您在内部使用任何实现,并创建一个工厂方法(或使用 DI)来构造对象。
不幸的是,这确实需要大量的简单传递(仅调用 COM 对象的包装方法)。然而,它是一种非常强大、面向未来的操作方式,让您可以使用简单、类型安全的 API。
If you're only using .NET 3.5, the best option would probably be to write your own interfaces that expose the exact functionality you require, and then implement the interfaces using IS 2009 and IS 2010. This allows you to use any implementation internally, and create a factory method (or use DI) to construct the objects.
Unfortunately, this does require a fair amount of simple pass through (wrapper methods that just call the COM object). However, it's a very robust, future proof way of operating, and lets you work with a simple, typesafe API.
如果您愿意,您可以自定义运行时可调用包装器,以便类型名称保持不变
If you are so inclined you could customize the run time callable wrapper so the type names are constant
如果您愿意放弃类型安全,
dynamic
会有所帮助,但您说它不适合您。但是,通过使用 dynamic rel="nofollow noreferrer">一个简单的帮助器类,用于隐藏反射噪音。它无法完成
dynamic
关键字可以完成的所有操作,但它仍然可能适合您。If you're happy to give up type safety,
dynamic
would be helpful, but you say it's not available to you.But you can get pretty close to
dynamic
in older versions of the language, by using a simple helper class to hide the noise of reflection. It doesn't do everything that thedynamic
keyword can do, but it still might work for you.思考这个问题,我认为我看到了一种可能的解决方案,以不同的方式完成,但它有点深奥。
引用是 ItemGroup 中 msbuild(项目)文件的一部分。您可以通过在 proj 文件中包含的项目中的另一个 msbuild 文件中包含此特定引用来将其外部化。
最后,您可以根据查找 COM 接口并确定引用包含的内容的某些逻辑来生成此外部 MSBUILD 文件 T4。
Thinking round the issue I think I see a possible solution done a different way but its a bit esoteric.
References are part of the the msbuild (project) file in an ItemGroup. You can externalise this by having this particular reference in another msbuild file in the project included in the proj file.
Finally you can make this external MSBUILD file T4 generated based on some logic that looks up the COM interface and determines what the reference contains.
使用 VB.NET 创建强类型包装器。然后您可以从 C# 应用程序调用该包装器。
Use VB.NET to create a strongly typed wrapper. Then you can call that wrapper from your C# application.