Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 需要“";初始化";方法在使用前调用-可以吗?_C#_.net - Fatal编程技术网

C# 需要“";初始化";方法在使用前调用-可以吗?

C# 需要“";初始化";方法在使用前调用-可以吗?,c#,.net,C#,.net,在我的项目中,我有多个“服务”静态类,它们应该可以在整个项目中轻松访问,因此它们是静态的。但是,要初始化它们,我必须向它们传递仅在启动时可用的数据,这会产生类似以下代码: public static class VisualStudioEvents { private static Data _data; public static void Initialize(Data data) { _data = data; } public

在我的项目中,我有多个“服务”静态类,它们应该可以在整个项目中轻松访问,因此它们是静态的。但是,要初始化它们,我必须向它们传递仅在启动时可用的数据,这会产生类似以下代码:

public static class VisualStudioEvents
{
    private static Data _data;

    public static void Initialize(Data data)
    {
        _data = data;
    }

    public static void Func()
    {
        AssertInitialized(_data);

        // Code of actual Func() goes here.
    }
}
你觉得怎么样?这里是否应该采用不同的设计模式?或者这种设计可以接受吗


谢谢

对于单例模式,这可能是一个很好的例子,您可以在构造函数中调用initialize,将
数据
作为类成员,如果
数据
不可用,则抛出异常

但是,您问题中的
数据
尽可能通用,因此根据其用途/可用性,可能有更好的方法来协调此初始化


编辑过的

我会很满意的。我要做的唯一改变是只强制执行一次:

    public static void Initialize(Data data)
    {
        if (data == null) throw new ArgumentNullException("data");
        if (Interlocked.CompareExchange(ref _data, data, null) != null)
        {
            throw new InvalidOperationException("Already initialized");
        }
    }

哦-我想
数据
也应该是不可变的,以避免人们意外更改配置。

名称
VisualStudioEvents
似乎表明该类是代码和实际Visual Studio extensions API之间的抽象的一部分

如果这是正确的,那么您将希望在单元测试中模拟
VisualStudioEvents
。我根本不会把它变成一个静态类


编辑:如评论所述,链接的博客文章可能过于激进。就个人而言,我认为静态方法只有在它们包含本应成为应用程序一部分的代码时才是有害的。将组件代码放在静态方法中通常会导致单元测试和依赖项注入出现问题

您可以尝试使用而不是静态类。这也会使测试代码变得更容易

我强烈反对静态类使用state,它与全局变量没有区别,带有state的静态类只是将全局变量包装到一个类中。和

我认为您应该得到某种解决方案,这将允许您获得helper类的非静态、已经初始化的实例。您的IoC容器可以在内部使用singleton,以确保使用单个配置对象

例如,结构可以是:

public class VisualStudioEvents
{
    public VisualStudioEvents(VisualStudioEventsConfig config)
    {
        // ...
    }

    // ...
}

在应用程序初始化时,您可以创建一个
VisualStudioEventsConfig
实例,对其进行配置,并将其添加到IoC容器中,作为该类型使用的唯一实例。然后,对
VisualStudioEvents
实例的每次调用都将使用这个准备好的配置实例进行初始化。

Slomojo:但是。。。在这种情况下,任何试图使用GetInstance方法访问singletone实例的人都需要向它传递参数,即使它已经初始化了……很抱歉,但是您没有提供足够的用例信息来说明这是一个问题。请详述你问题中的细节。(例如,发送给初始化的数据是什么)到了测试时,您会希望它不是单例。仅实例化一次,将其存储在全局可访问的位置。程序的其他部分不会意外地创建新对象,因为它们没有构造函数所需的数据。Slomojo:无需道歉:)我感谢您的输入。我要说的是,它是静态对象的部分原因是为了方便从项目中的各个地方访问它。但是,只有在“数据”可用的情况下才调用初始化函数一次。如果需要在这个静态对象中调用一个方法的任何人都需要向它传递数据,这将使它更加麻烦。+1,我以前从未见过
互锁。compareeexchange
。我去MSDN@Alastair——关键是它是线程安全的,不需要锁。实际上,您可能只需要初始化它一次,然后将它存储在全局位置(即应用程序主类的静态成员)。全局状态通常是个坏主意。jalf写道,这与这种情况高度相关,并解释了为什么单例模式实际上会使情况变得更糟。@CodeInChaos:可能唯一比拥有全局对象更糟的事情是,对象的设计是基于它是全局的知识。这就是可测试性真正崩溃的地方。虽然全局状态几乎总是不好(OPs设计使用全局状态),但说(无副作用)静态方法总体上不好是相当有争议的,我个人不同意。@CodeInChaos:也许你对我的回答有不同的解释,但我并不是说它们总体上是坏的。我想说的是,如果静态方法提供了需要在单元测试中模仿的功能,那么它们就是不好的。至少你链接的博客更激进,认为基本上所有的静态方法都是邪恶的。@CodeInChaos:同意。我添加了一些细微差别。很有趣。我不知道国际奥委会的情况,我现在正在读关于结构图的书,它非常有趣。谢谢你的参考,我会考虑你的解决方案。我有点困惑,但不是在StructureMap,ObjutFrand本身就是一个带有状态的静态类吗?毕竟,您确实需要调用ObjectFactory.Initialize函数。。。也许它使所有服务的初始化更加集中在一个地方,但是,它看起来非常像一个全局变量..我没有使用StructureMap的经验,但我对这种全局初始化非常熟悉,至少它不是您自己的全局状态,您不打算在初始化后直接使用它。但事实上,这是一个有趣的问题:)