我编写了一个 C# 程序和库,允许用户更轻松地使用特定专有模拟器的 COM 接口。
目前,我必须为我希望支持的每个版本的模拟器构建和分发不同版本的 C# 库。开发模拟器的公司定期发布新版本,每个新版本都会有一个递增的主版本号。据我所知,版本之间的 COM 接口尚未发生任何变化,因此从我的角度来看,调用和行为都是相同的。但是,如果我针对模拟器版本 9.0 构建库和安装程序,并且用户安装了版本 10.0,则我的 C# 程序无法找到模拟器的 COM 接口。 (即使对模拟器进行较小的升级也会导致 COM 接口的主要版本发生变化。)因此,我必须针对每个受支持的模拟器版本构建我的库。这很烦人,我宁愿分发一个在安装时正确查找并链接到最新模拟器的库。
看来必须有办法做到这一点。我认为这个页面可能描述了该方法:如何:包装类型库的多个版本 http://msdn.microsoft.com/en-us/library/1565h6hc.aspx。但这似乎对我不起作用。
当然,也有可能是我没有做对。我按照说明获取了两个版本的 COM 接口的 .il 文件。 9.0 和 10.0。但我对下一步感到困惑,找不到例子:
使用文本编辑器,在 Tlbimp.exe 添加的属性下方插入第二个 PrimaryInteropAssemblyAttribute 属性。包括代表第二类型库版本的主要版本号和次要版本号。
我不确定是否应该复制程序集块,或者只是复制块内的行(它没有我可以看到的版本信息。)所以我像这样复制了程序集块:
enter code here
.assembly Interop.Happ
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = ( 01 00 04 48 61 70 70 00 00 )
.custom instance void
[mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32, int32) = ( 01 00 09 00 00 00 00 00 00 00 00 00 )
////////////// [SNIP] ///////////////
.ver 9:0:0:0
}
.assembly Interop.Happ
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = ( 01 00 04 48 61 70 70 00 00 )
.custom instance void
[mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32, int32) = ( 01 00 0A 00 00 00 00 00 00 00 00 00 )
////////////// [SNIP] //////////////
.ver 10:0:0:0
}
.module Interop.Happ.dll
这不起作用,但我看不出我的其他解释如何可能。谁能看到我做错了什么吗?我是否完全走错了路,或者我只是组合了 .il 文件的错误部分?
我们为我们的产品解决了这个问题,不使用tlbimp.exe
并提供定制包装。
我们的包装器仅为接口提供 .NET 定义,忽略类型库和组件类。用户必须使用 Activator API 从 ProgID 获取实例,当然,ProgID 可以成为其应用程序的配置参数。
这是可以管理的,因为接口是不可变的,因此我们必须为每个接口只创建一次包装类,即使实现不断发展。
包装示例:
[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLogger
{
[DispId(1000)]
string Name { [return: MarshalAs(UnmanagedType.BStr)] get; }
[DispId(1001)]
void LogSimple (long level, [MarshalAs(UnmanagedType.BStr)] string message, object location);
}
[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLoggingHierarchy
{
[DispId(1000)]
string Type { [return: MarshalAs(UnmanagedType.BStr)] get; }
[DispId(1001)]
IProdistLogger CreateLogger ([MarshalAs(UnmanagedType.BStr)] string name);
}
[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLogging
{
[DispId(1000)]
IProdistLoggingHierarchy CreateHierarchy ([MarshalAs(UnmanagedType.BStr)] string type, object configuration);
}
客户端示例:
public class Program
{
public static void Main (string[] args)
{
IProdistLogging logging = (IProdistLogging)System.Activator.CreateInstance(Type.GetTypeFromProgID("prodist.logging.Logging.5.4"));
IProdistLoggingHierarchy hierarchy = logging.CreateHierarchy("log4cxx", null);
return;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)