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