重构静态类以用于依赖注入

hat*_*enn 14 c# singleton refactoring dependency-injection static-classes

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

我想把它作为一个单独的类引入.这样它将在实例类中,但只有一个实例,因此我不必担心更改设置或初始化.您如何看待这种方法?我对依赖注入模式很新,我不确定单例模式是否是一个好的解决方案?您对类似案例的解决方案是什么?

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

编辑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)
Run Code Online (Sandbox Code Playgroud)

Ste*_*art 10

如果您只需要在启动时设置一次设置,那么我建议创建一个非静态包装类,它在自己的静态构造函数中完成静态类的所有初始化.这样你可以放心,它只会发生一次:

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

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

    public void Method1()
    {
        UnManagedStaticClass.Method1();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您每次调用它时都需要更改设置,并且希望使实例具有线程安全性,那么我建议您锁定静态对象,这样您就不会意外地覆盖静态设置.仍然被另一个线程使用:

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();
        }
    }
}   
Run Code Online (Sandbox Code Playgroud)

如果您需要将初始化参数传递到类的实例构造函数中,那么您也可以通过使用静态标志字段来执行此操作:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你还需要每次重新初始化,但是你担心性能因为重新初始化太慢,那么唯一的另一个选择(在可怕的单例之外)是自动检测你是否需要重新初始化和只在必要时才这样做.至少那时,唯一的时间是两个线程同时使用两个不同的实例.你可以这样做:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)