In my project I have multiple "service" static classes that should be easily accessible across the project, and thus they are static. However, to 开发者_如何学编程to initialize them, I have to pass them data that is only available during start-time, which results in code similar to this:
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.
}
}
What do you think about that? Is there a different design patter that should be applied here? Or is this design acceptable?
Thanks!
I'd be pretty comfortable with that. The only change I'd make would be to enforce it as once-only:
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");
}
}
oh -I guess Data
should also be immutable to avoid people changing the config unexpectedly.
I would strongly discourage static classes having state, it doesn't differ from global variables, static classes with state just wraps globals into a class. And we all know why globals are bad.
I think you should get some kind of inversion of control solution, that will allow you to get non-static, already initialized instance of your helper class. Your IoC container may use singleton internally to ensure there is single configuration object used.
For example the structure may be:
public class VisualStudioEvents
{
public VisualStudioEvents(VisualStudioEventsConfig config)
{
// ...
}
// ...
}
and on application initialization you can create an VisualStudioEventsConfig
instance, configure it and add to IoC container as the only instance to be used for the type. Then, every call for VisualStudioEvents
instance will be initialized with this prepared configuration instance.
This is probably a good case for a Singleton pattern, you could call initialize in the constructor, with the Data
as a class member, throwing an exception if Data
is unavailable.
However, the Data
in your question is as generic as you could be, so depending on it's purpose/availability there is likely a better way to orchestrate this initialization.
edited
The name VisualStudioEvents
seems to indicate that this class is part of an abstraction between your code and the actual Visual Studio extensions API.
If that is correct, then VisualStudioEvents
is something you will want to mock in your unit tests. I wouldn't make this a static class at all. Static methods are death to testability.
edit: as remarked in the comments, the linked blog post is perhaps too radical. Personally I think that static methods are only evil when they contain code that should be part of a component. Putting component code in static methods causes static cling problems with unit testing and dependency injection in general.
You can try to use the singleton pattern instead of a static class. That would also make it easier to test the code.
精彩评论