c# - 如何在 C# 中管理多个版本的非托管 DLL 调用的使用?

标签 c# dll unmanaged dllimport multiple-versions

我想知道是否有人可以为我指出正确的方向,我对 C# 还很陌生,所以对我宽容点。

我的代码使用非托管 DLL,它是提供的用于与智能卡读卡器接口(interface)的 API,我无法控制 DLL,我只是想将其包装在 C# 中以使其更易于使用。到目前为止,我已经设法做到了这一点,但我现在发现需要测试此 DLL 的多个版本,这些版本的入口点相同,但参数可以不同。 p>

我尝试了一些类似的方法来组织我的包装类;

internal static class UnSafeNativeMethods
{
    internal static class READER
    {
        internal static class SDK20
        {
            [DllImport(dllpath, EntryPoint = "CV_SetCommunicationType")]
            internal static extern int CV_SetCommunicationType(byte type);
            ...
        }

        internal static class SDK21
        {
            [DllImport(dllpath, EntryPoint = "CV_SetCommunicationType")]
            internal static extern int CV_SetCommunicationType(byte type);
            ...
        }
    }
}

但是在检查要使用哪个调用时,它会产生非常难看的代码;

ReaderSDK sdk = ReaderSDK.SDK20  //Could come from a argument passed in or set in an 
                                 //instantiated class
...
switch (sdk)
{
    case ReaderSDK.SDK20:
        UnSafeNativeMethods.READER.SDK20.CV_SetCommunicationType(0x0);
        break;
    case ReaderSDK.SDK21:
        UnSafeNativeMethods.READER.SDK21.CV_SetCommunicationType(0x0);
        break;
    ...
}

这对我来说似乎很困惑,想知道是否有人可以指出我正确的方向......


编辑:离开下面的评论,我想出了一些示例代码,但仍然不确定我是否走在正确的轨道上,因为我的开关仍然存在,但它现在是混凝土的一部分工厂类。

public enum ConnectionType
{
    RS232 = 0x0,
    USB = 0x1,
    UDP = 0x2
}

interface INativeMethods
{
    string Name();
    void SetCommunicationType(ConnectionType type);
}

class SDK20 : INativeMethods
{
    public string Name()
    {
        return "SDK Version 2.0";
    }

    // Thanks to @dzendras for this!!
    public void SetCommunicationType(ConnectionType type)
    {
        int result = UnSafeNativeMethods.READER.SDK20.CV_SetCommunicationType((byte)type);
        switch (result)
        {
            case 0:
                return;
            case 1:
                throw new NotSupportedException("Communication type not supported");
            case 2:
                throw AnyOtherMeaningfulException("Its message");
        }
    }


}

class SDK21 : INativeMethods
{
    public string Name()
    {
        return "SDK Version 2.1";
    }

    // Thanks to @dzendras for this!!
    public void SetCommunicationType(ConnectionType type)
    {
        int result = UnSafeNativeMethods.READER.SDK21.CV_SetCommunicationType((byte)type);
        switch (result)
        {
            case 0:
                return;
            case 1:
                throw new NotSupportedException("Communication type not supported");
            case 2:
                throw AnyOtherMeaningfulException("Its message");
        }
    }
}

class NativeMethodsFactory
{
    private static NativeMethodsFactory instance = new NativeMethodsFactory();
    private NativeMethodsFactory()
    {

    }

    public static NativeMethodsFactory Instance
    {
         get { return NativeMethodsFactory.instance; }
    }
    public INativeMethods Get(ReaderSDK version)
    {
        switch (version)
        {
            case ReaderSDK.SDK20:
                return new SDK20();

            case ReaderSDK.SDK21:
                return new SDK21();

            default:
                return new SDK20();
        }
    }
}

我的方向正确吗?

这就是我现在实现对 SDK 的调用的方式...

// sdk passed in as enum, NativeMethods stored as class member.
NativeMethods = NativeMethodsFactory.Instance.Get(sdk);
...
NativeMethods.SetCommunicationType(ConnectionType.USB);

最佳答案

使用模式策略

一些关于模式的链接:

http://www.oodesign.com/strategy-pattern.html

Real World Example of the Strategy Pattern

在工厂模式的帮助下如何使用策略模式最终实现的一些示例。

INativeMethods nativeMethods = NativeMethodsFactory.Get(UnsafeSdkVersion.V1);
nativeMethods.CV_SetCommunicationType(aType);

优点:

  1. 通过接口(interface)和工厂解耦
  2. 无开关
  3. 易于添加新版本,所有其他代码都独立于要使用的版本。

关于c# - 如何在 C# 中管理多个版本的非托管 DLL 调用的使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11106320/

相关文章:

c# - 使用C#从数据库中读取图像?

asp.net - .NET 应用程序中的非托管资源消耗了大量内存

c# - 以谓词为参数的方法

C# 正则表达式匹配与拆分相同字符串

C# 4.0 将 .dll 程序集与 .NET 合并

c++ - 无法使用 Sql Anywhere 16 找到加密 dll dbfips16.dll

c++ - 编译器之间的 DLL 兼容性

c# - 非托管 C++ Win32 API 或 C#?

c# - 为非托管程序集动态创建包装器?

c# - 防止数据绑定(bind) DataGridView 在编辑时进行排序