重构一个静态类与依赖注入来使用 [英] Refactoring a static class to use with dependency injection

查看:744
本文介绍了重构一个静态类与依赖注入来使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们需要在我们的代码有静态方法使用一个非托管库。我想介绍库操作在我的代码的依赖关系。而除了有静态方法,库中有一个初始化方法和设置方法,都是全球性的。所以我不能只是把这个包在一个实例类,因为如果一个实例更改了设置,所有其他实例都将受到影响,如果一个实例被初始化,所有其他实例将重新初始化。



我想到了引入它作为一个单独的类。这样,这将是一个实例类,但只会有这样我就不必担心改变设置或初始化一个实例。你觉得这种做法是什么?我很新的依赖注入模式,我不知道,如果单件模式是一个很好的解决方案? ?将您的解决方案是一个类似的案件是什么



编辑:初始化需要一个参数了,所以我不能只锁定方法。电话和重新初始化并更改设置每次调用时间



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

 公共静态无效初始化(INT someParameter)
//参数只能通过重新initalization改变了
/ /将所有设置复位到它们的默认值。

公共静态浮动[]方法一(INT someNumber,浮动[]的someArray)

公共静态无效ChangeSetting(字符串settingName,诠释settingValue)


解决方案

如果您只需要一次,在启动时设定的设置,然后我会建议作出非静态包装类由它来完成静态类的所有初始化在自己的静态构造函数。这样,你可以放心,它只会发生一次:

 公共类MyWrapper 
{
公MyWrapper()
{
//执行任何必要的实例初始化这里
}

静态MyWrapper()
{
UnManagedStaticClass.Initialize( );
UnManagedStaticClass.Settings = ...;
}

公共无效方法1()
{
UnManagedStaticClass.Method1();
}
}



不过,如果您需要更改设置的每个时间你怎么称呼它,你想使你的情况下,线程安全的,那么我会建议锁定一个静态的对象,这样你就不会意外覆盖静态设置,而他们仍然被其他线程:

 公共类MyWrapper 
{
公共MyWrapper()
{
//做任何必要的在此实例初始化
}

静态MyWrapper()
{
UnManagedStaticClass.Initialize();
}

静态对象lockRoot =新的对象();

公共无效方法1()
{
锁(lockRoot)
{
UnManagedStaticClass.Settings = ...;
UnManagedStaticClass.Method1();
}
}
}

如果您需要通过初始化参数到您的类的实例构造函数,那么你可以做到这一点通过具有静态标志字段:

 公共类MyWrapper 
{
公共MyWrapper(InitParameters p)
{
锁(lockRoot)
{
如果(!初始化)
{
UnManagedStaticClass。初始化(对);
初始化= TRUE;
}
}
}

静态布尔初始化= FALSE;
静态对象lockRoot =新的对象();

公共无效方法1()
{
锁(lockRoot)
{
UnManagedStaticClass.Settings = ...;
UnManagedStaticClass.Method1();
}
}
}

如果您还需要重新-initialize每一次,但你关心性能,因为重新初始化速度太慢,那么唯一的选择(可怕的单外)是,如果你需要重新初始化并在必要的时候只能做它来自动检测。至少然后,它会发生的唯一时间是当两个线程使用两个不同的实例同时。你可以做这样的:

 公共类MyWrapper 
{
公共MyWrapper(InitParameters initParameters,设置设置)
{
this.initParameters = initParameters;
this.settings =设置;
}

私人InitParameters initParameters;
私人设置设置;
静态MyWrapper currentOwnerInstance;
静态对象lockRoot =新的对象();

私人无效InitializeIfNecessary()
{
如果(currentOwnerInstance =这个!)
{
currentOwnerInstance =这一点;
UnManagedStaticClass.Initialize(initParameters);
UnManagedStaticClass.Settings =设置;
}
}

公共无效方法1()
{
锁(lockRoot)
{
InitializeIfNecessary();
UnManagedStaticClass.Method1();
}
}
}


We need to use an unmanaged library in our code that has static methods. I'd like to introduce the library operation as a dependency in my code. And apart from having static methods, the library has an initialization method and a settings method, both are global. So I can't just wrap this in an instance class, because if one instance changes a setting, all other instances will be affected, and if one instance gets initialized, all other instances will be reinitialized.

I thought about introducing it as a singleton class. This way it will be in an instance class, but there will only be one instance thus I won't have to worry about changing the settings or initialization. What do you think about this approach? I'm pretty new to the dependency injection pattern and I'm not sure if the singleton pattern is a good solution? What would your solution be to a similar case?

Edit: The initialization takes a parameter too, so I can't just lock the method calls and re-initialize and change settings every time it is called.

Edit 2: Here are the signatures of some methods:

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)

解决方案

If you only need to set the settings once at start up, then I would recommend making a non-static wrapper class which does all the initialization of the static class in its own static constructor. That way you can be assured that it will only happen once:

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

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

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

However, if you need to change the settings each time you call it, and you want to make your instances thread-safe, then I would recommend locking on a static object so that you don't accidentally overwrite the static settings while they're still in use by another thread:

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();
        }
    }
}   

If you need to pass initialization parameters into your class's instance constructor, then you could do that too by having a static flag field:

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();
        }
    }
}

If you also need to re-initialize each time, but you are concerned about performance because re-initializing is too slow, then the only other option (outside of the dreaded singleton) is to auto-detect if you need to re-initialize and only do it when necessary. At least then, the only time it will happen is when two threads are using two different instances at the same time. You could do it like this:

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();
        }
    }
}

这篇关于重构一个静态类与依赖注入来使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆