我们需要在代码中使用具有静态方法的非托管库。我想将库操作作为依赖项引入我的代码中。除具有静态方法外,该库还具有初始化方法和设置方法,两者都是全局的。因此,我不能仅仅将其包装在一个实例类中,因为如果一个实例更改设置,则所有其他实例都会受到影响,并且如果一个实例被初始化,则所有其他实例都将被重新初始化。

我考虑过将其作为单例类(class)进行介绍。这样,它将在一个实例类中,但是只有一个实例,因此我不必担心更改设置或初始化。您如何看待这种方法?我对依赖项注入(inject)模式还很陌生,我不确定单例模式是否是一个好的解决方案?对于类似的情况,您的解决方案是什么?

编辑:初始化也带有一个参数,所以我不能只锁定方法调用并在每次调用时重新初始化和更改设置。

编辑2:这是一些方法的签名:

public static void Initialize(int someParameter)
// Parameter can only be changed by re-initalization which
// will reset all the settings back to their default values.

public static float[] Method1(int someNumber, float[] someArray)

public static void ChangeSetting(string settingName, int settingValue)

最佳答案

如果您只需要在启动时设置一次设置,那么我建议您制作一个非静态包装器类,该类在其自己的静态构造函数中对静态类进行所有初始化。这样,您可以放心,它只会发生一次:

public class MyWrapper
{
    public MyWrapper()
    {
        // Do any necessary instance initialization here
    }

    static MyWrapper()
    {
        UnManagedStaticClass.Initialize();
        UnManagedStaticClass.Settings = ...;
    }

    public void Method1()
    {
        UnManagedStaticClass.Method1();
    }
}

但是,如果您需要在每次调用时更改设置,并且希望使实例成为线程安全的,那么我建议您锁定静态对象,以免在静态对象被静态设置覆盖时意外覆盖它们。仍被另一个线程使用:
public class MyWrapper
{
    public MyWrapper()
    {
        // Do any necessary instance initialization here
    }

    static MyWrapper()
    {
        UnManagedStaticClass.Initialize();
    }

    static object lockRoot = new Object();

    public void Method1()
    {
        lock (lockRoot)
        {
            UnManagedStaticClass.Settings = ...;
            UnManagedStaticClass.Method1();
        }
    }
}

如果需要将初始化参数传递到类的实例构造函数中,则也可以通过具有静态标志字段来实现:
public class MyWrapper
{
    public MyWrapper(InitParameters p)
    {
        lock (lockRoot)
        {
            if (!initialized)
            {
                UnManagedStaticClass.Initialize(p);
                initialized = true;
            }
        }
    }

    static bool initialized = false;
    static object lockRoot = new Object();

    public void Method1()
    {
        lock (lockRoot)
        {
            UnManagedStaticClass.Settings = ...;
            UnManagedStaticClass.Method1();
        }
    }
}

如果您每次也需要重新初始化,但由于重新初始化太慢而担心性能,那么唯一的选择(在可怕的单例之外)是自动检测是否需要重新初始化并重新启动。仅在必要时这样做。至少到那时,唯一的情况是两个线程同时使用两个不同的实例。您可以这样做:
public class MyWrapper
{
    public MyWrapper(InitParameters initParameters, Settings settings)
    {
        this.initParameters = initParameters;
        this.settings = settings;
    }

    private InitParameters initParameters;
    private Settings settings;
    static MyWrapper currentOwnerInstance;
    static object lockRoot = new Object();

    private void InitializeIfNecessary()
    {
        if (currentOwnerInstance != this)
        {
            currentOwnerInstance = this;
            UnManagedStaticClass.Initialize(initParameters);
            UnManagedStaticClass.Settings = settings;
        }
    }

    public void Method1()
    {
        lock (lockRoot)
        {
            InitializeIfNecessary();
            UnManagedStaticClass.Method1();
        }
    }
}

10-07 13:26
查看更多