c# - 重构静态类以与依赖注入(inject)一起使用

标签 c# dependency-injection refactoring singleton static-classes

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

我考虑过将其作为单例类引入。这样它将在一个实例类中,但只有一个实例,因此我不必担心更改设置或初始化。您如何看待这种方法?我对依赖注入(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();
        }
    }
}

关于c# - 重构静态类以与依赖注入(inject)一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14894980/

相关文章:

c# - 使用 Windows Phone 在运行时加载 xaml viewmodel

c# - 在 Quartz.Net 中重构作业定义(通用函数)

c# - 如何使用 Visual Studio 顺利更改重命名我的项目文件和类文件?

unit-testing - 大量设置代码 : Does it indicate an issue and what strategies exist to deal with it

java - Guice:在创建模块之前实例化单例

c# - Windows.UI.Xaml.dll 中的 UWP 应用程序在 Release模式下崩溃

c# - Web 应用程序之间的 Asp.Net Core DataProtection 无法在 Azure 上运行

c# - Microsoft.Graph 获取一个组的所有用户

oop - 使用构造函数依赖注入(inject)时提供依赖项的后备/默认值?

c# - 来自特定程序集的 Unity DI 自动注册