Ok, so I know you can't have objects in a static class but i need a class that i can hold objects that are accessible from different classes. I am making a dll that will provide extended functionality to another program so i can't just inherit or pass classes around either. if need be i can just maybe make the properties of each object i need to be in the static class which would work but not be as friendly as i would like. anyone have any other ideas on how to accomplish something like this?
Actually, you can have objects in a static class -- they just have to be static objects.
For instance:
public static class SharedObjects
{
private static MyClass obj = new MyClass();
public static MyClass GetObj()
{
return obj;
}
}
And from elsewhere in your program you can call instance methods/properties/etc.:
SharedObjects.GetObj().MyInstanceMethod();
One option is to have a class with the accessors methods accessing a static object (or objects). The other parts of your system can use the class either as static or as a non-static. Here is the code:
public class GlobalInformation {
public static GlobalInformation CreateInstance() {
// Factory method through GlobalInformmation.CreateInstance()
return new GlobalInformation();
}
public GlobalInformation() {
// Regular use through new GlobalInformation()
}
static GlobalInformation() {
// Static initializer called once before class is used.
// e.g. initialize values:
_aString = "The string value";
}
public string AccessAString {
get {
return _aString;
}
}
public Foo AccessAnObject() {
return _anObject;
}
private static string _aString;
private static readonly Foo _anObject = new Foo();
}
Other parts of your system would use it as follows. Option 1:
var globalInfo = GlobalInformation.CreateInstance();
var aString = globalInfo.AssessAString;
var anObj = globalInfo.AccessAnObject();
Option 2:
var globalInfo = new GlobalInformation();
var aString = globalInfo.AssessAString;
var anObj = globalInfo.AccessAnObject();
Option 2 would be my preferred one (I'd remove the static factory method CreateInstance()) as you could change the implementation at any time including making (some of) the fields non-static. It would appear to be a regular class while sharing data.
Related
I have a static class with a static constructor. I need to pass a parameter somehow to this static class but I'm not sure how the best way is.
What would you recommend?
public static class MyClass {
static MyClass() {
DoStuff("HardCodedParameter")
}
}
Don't use a static constructor, but a static initialization method:
public class A
{
private static string ParamA { get; set; }
public static void Init(string paramA)
{
ParamA = paramA;
}
}
In C#, static constructors are parameterless, and there're few approaches to overcome this limitation. One is what I've suggested you above.
As per MSDN, A static constructor is called automatically to initialize the class before the first instance is created. Therefore you can't send any parameters.
CLR must call a static constructor, how will it know which parameters to pass it?
So don't use a static constructor.
Here's the work around for your requirement.
public class StaticClass
{
private int bar;
private static StaticClass _foo;
private StaticClass() {}
static StaticClass Create(int initialBar)
{
_foo = new StaticClass();
_foo.bar = initialBar;
return _foo;
}
}
Static constructors have the following properties:
A static constructor does not take access modifiers or have parameters. A static constructor is called automatically to
initialize the class before the first instance is created or any
static members are referenced.
A static constructor cannot be called directly.
The user has no control on when the static constructor is executed in the program.
A typical use of static constructors is when the class is using a log file and the constructor is used to write entries to this file.
Static constructors are also useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary
method.
If a static constructor throws an exception, the runtime will not invoke it a second time, and the type will remain uninitialized for
the lifetime of the application domain in which your program is
running.
If by "HardCodedParameter" you really mean hard coded, you can use constants.
public static class YoursClass
{
public const string AnotherHardCodedParam = "Foo";
}
public static class MyClass
{
private const string HardCodedParam = "FooBar";
static MyClass()
{
DoStuff(MyClass.HardCodedParam);
DoStuff(YoursClass.AnotherHardCodedParam);
}
}
Also, you can use static readonly properties.
Constructors on non-static class have have the benefit to ensure they're properly initialized before they're actually being used.
Since static classes don't have this benefit, you have to make ensure that yourself.
Use a static constructor with an obvious name, then in the relevant portion of your static procedures check to make sure the initialization has been performed.
The example below assumes your want to "initialize" your static class with a Form object.
public static class MyClass
{
private static Form FormMain { get; set; }
public static void Init(Form initForm)
{
FormMain = initForm;
}
private static bool InitCheck()
{
return FormMain != null ? true: false;
}
public static void DoStuff()
{
if (InitCheck())
{
// Do your things
}
else
{
throw new Exception("Object reference not set to an instance of an object");
}
}
}
i am a little confused by multi-thread access risk on a static property in C#.
public class MyClass
{
public static MyClass Static
{
get
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
}
This example class provides a static property that create a new instance of MyClass,
like a method:
public class MyClass
{
public static MyClass Static()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
Obviously, this property is not a "storage" box for an instance of MyClass, but it behaves like a static method (that, if i reading good a msdn article, is completely thread-safe).
My question is: i risk something with using this concept ?
Especially in a web or multi-thread enviroinment ?
There is a no particular utility in using it, only for simple reading and cleaning code:
MyClass.Static.SomeProperty = "Something";
is more clear than
MyClass.Static().SomeProperty = "Something";
All help will be appreciated
Thanks
In both your examples you're returning a new instance of MyClass every time the property is accessed. There is no danger that you'll have any concurrency issues when multiple threads access the static property method at the same time, because they're actually modifying the properties of their own instance of MyClass and not sharing it between them.
If you had something like this instead:
public class MyClass
{
private static MyClass _myClass;
public static MyClass Static
{
get
{
return _myClass ?? (_myClass = new MyClass());
}
}
}
...then you'd cause problems when two threads attempted to write/read properties of the resulting MyClass instance, because they're operating on the same MyClass reference _myClass.
Even so, there are two issues with the code you've posted:
You need to change it to a method and rename it, because it's actually creating something, not accessing a static version of anything. Then you can operate on the return value. Something like this:
public class MyClass
{
public static MyClass Create()
{
var c = new MyClass();
c.SomeProperty = "12345";
c.OtherProperty = DateTime.Now.ToString();
return c;
}
}
Then use it like this:
var myClass = MyClass.Create();
myClass.SomeProperty = "Stuff";
The way you're setting properties currently means their values aren't persisted, because a new MyClass is created the next time the Static property is accessed.
If when you set SomeProperty you actually want a static instance to be updated you'll need to lock on a static object to solve the multi threading issue - something like this:
public static class MyClass
{
private static readonly object locker = new object();
private static string someProperty;
public void SetSomeProperty(string val)
{
lock (locker)
{
someProperty = val;
}
}
public void GetSomeProperty()
{
lock (locker)
{
return someProperty;
}
}
}
It seems that you are creating a static factory method that will give you a fully instantiated object.
Threading would not be an issue here because every time you call this method or property you are creating a new object. If 2 threads call the same method at the same time they will each keep on working on the object they are dealing with
Having said that - Perhaps you should reexamine how you are using the class - because if you call this in your code
MyClass.Static.SomeProperty = "Something";
You are basically throwing away the object after it has been instantiated
you would need to assign it to a variable and store it. - the next time you call that function you will receive a new object.
Perhaps I was not able to explain properly, my question was referred multithreaded access on static properties.
I can confirm that they are thread-safe, if the returned object is bound to the current thread.
Here is the example of what I implemented:
public interface IObjectFactory
{
T CreateOrReuse<T>() where T : class, new();
T CreateOrReuse<T>(string key) where T : class, new();
T CreateOrReuse<T>(string key, params object[] args) where T : class;
}
public class ThreadObjectFactory : IObjectFactory
{
// implementation to create and store into the Thread Data
}
public class HttpSessionObjectFactory : IObjectFactory
{
// implementation to create and store into the current session
}
Now the singleton:
public class MyClass
{
public int PageLoadCounter = 0;
public static MyClass Static
{
get
{
IObjectFactory factory = new HttpSessionObjectFactory();
return factory.CreateOrReuse<MyClass>();
}
}
}
And this is the final use:
public class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyClass.Static.PageLoadCounter++;
}
}
Thanks for the replies, even if the question was not very clear
I saw implementation like that:
class MyClass
{
private static readonly MyClass _instance = new MyClass();
public static MyClass Instance{
get{ return _instance; }
}
}
Why not make it simple?
class MyClass
{
public static readonly MyClass Instance = new MyClass();
}
You can expose public fields like this - but I prefer not to. If you leave it as a property, you can change the implementation later. For example, suppose you later add a static method which you want to be able to call without initializing the singleton - with the property version, you could change the code to:
public sealed class MyClass
{
public static MyClass Instance { get { return InstanceHolder.instance; } }
private MyClass() {}
private static class InstanceHolder
{
internal static readonly MyClass instance = new MyClass();
}
public static void Foo()
{
// Calling this won't initialize the singleton
}
}
(With the original version, the singleton might be initialized, or it might not be - it's up to the CLR.)
That's just one example of why you might want to change the implementation later. With a property, you can do that - with a field, you can't.
What you've got there would work fine, but public fields are usually frowned upon in favour of Properties. You can change the implementation of the get { ... } without needing to change calling code. This would enable you to (for example) switch to lazy initialisation where the Instance is only created the first time it is used.
Note that although the calling code wouldn't need to change, it would change the signature of your class since a readonly property is different to a readonly field.
I would like to get an instance of a static class, but I can’t seem to do this without implementing a singleton wrapper on a non-static class– is this possible, or am I missing something?
public class MyInstanceTester
{
public MyInstanceTester()
{
//this is how i get a reference to a singleton now
MyClass instance1 = MyClass.Instance();
//this is what is would like to do (if only the compiler would let me)
MyStaticClass instance2 = MyStaticClass.Instance();
}
}
public class MyClass
{
private static MyClass _myInstance;
static MyClass()
{
_myInstance = new MyClass();
}
public static MyClass Instance()
{
return _myInstance;
}
}
public static class MyStaticClass
{
public static MyStaticClass Instance
{
get
{
return this;
}
}
}
There is no such thing as an instance of a static class. The singleton pattern simply returns the same instance of a class to repeated requests.
You may be getting confused by:
private static MyClass _myInstance;
This simply means that there will be a single instance of that particular object among all objects instantiated of the type that have _myInstance as a member.
A few notes:
The this keyword is not valid in a static member
If you have a static class then all members have to be static and so this will never be valid
A Singleton class cannot be a static class
Singletons declare a single static member to help ensure that only a single instance of that class exists
Note that a static reference to an object does not make the object static. Only the reference is static
Further reading: Jon Skeet has an excellent write up on implemeting Singletons in C# In Depth. I would suggest reading and studying this article until you grok it. It is quite good.
There is no reason to return a instance to a static class ( If the class is static there is no instance ).
You can access the class from everywhere, why returning a instance to it? I can't imagine any reason to do this.
Static class usage
To use a static class just write it like below:
MyStaticClass.MyMethod();
Int32 callCount = MyStaticClass.CallCount;
As you can see it doesn't even make sense to declare a variable because this would just look like this:
MyStaticClass msc = MyStaticClass.Instance();
msc.MyMethod();
Int32 callCount = msc.CallCount;
If you want to have a shorter name you just can use:
using MSC = MyNamespace.MyStaticClass;
From your comments I assume your solution would be:
Make your class non-static. (Just keep the methods static.)
Your terminology is wrong. Please read the MSDN article on the static keyword.
A static member cannot be referenced through an instance. Instead, it
is referenced through the type name.
A singleton is a class that only allows a single instance of itself. A common implimentation of this in C# is:
public class MyClass
{
private MyClass _value = null;
public MyClass Value {
get { return _value ?? (_value = new MyClass()); }
}
}
The major problem is here:
public static class MyStaticClass
{
public static MyStaticClass Instance
{
get
{
return this; //compile time error!
}
}
}
this refers to an instance of a class which does not make sense in a static class as there can be no instance of one. This by itself should make you realize that there is a fundamental error in what you are asking: "I would like to get an instance of a static class". You can not return an instance of a static class as a static class by definition can not be instantiated.
The singleton pattern just makes sure that you always return the same instance of a class. But said class can never be static.
I am working on a .NET based application, where some of the core application classes were designed with only static methods.
Example usage:
// static access.
Parameters.GetValue("DefaultTimeout");
// static access.
Logger.Log("This is an important message!");
There's already code out there that uses these static methods, so this "interface" cannot be changed.
These classes currently implement no interface. I would like to be able to separate the actual implementation of these classes from their interface.
The reason for this refactoring is that these objects will be used across AppDomain boundaries. I would like to be able to inject a "proxy" object that on non main-appdomains will invoke some other implementation instead of the default one.
To sum up, my questions are:
How can i easily transform objects with static-only access to an interface based design, such that their implementation may be replaced when needed (but keeping static access).
Once refactored, how/WHEN is the actual injection of the non-default implementation should occur?
Disclaimer: The following suggestion is based on the importance of not changing the calling side. I'm not saying it's the best option, just that I think it's suitable.
Disconnecting the Implementation
There is no way to have interfaces on static members, so if you don't want to change the calling code, the static will likely have to remain. That said, you can simply have your static class wrap an interface inside, so the static class itself doesn't have any implementation - it delegates all calls to the interface.
This all means you can leave your static class and any code that calls it in place. This will be like treating the static class as the interface (or contract), but having it internally swap out implementations based on the situation.
It also means your interface can have a different signature to the static class, as the interface doesn't have to conform to the calling code expectations - basically, it will turn your static class into a sort of Bridge.
Injecting the Implementation
In short: use a static constructor in order to resolve the given implementation of this interface.
Statics are per AppDomain normally (unless decorated with ThreadStaticAttribute, then per AppDomain/thread) so you can determine where you are and what implementation you need based on the current AppDomain (the static constructor will be called whenever the static is first used in the AppDomain). This means that once constructed, that particular static class's wrapped implementation will remain for the duration of the AppDomain (though you could implement methods to flush the implementation).
Cross AppDomain Calling
The code responsible for this can either be in the static classes or you can make one of the interface implementations simply a proxy manager to an AppDomain type. Any type for cross AppDomain calls will need to inherit MarshalByRefObject.
http://msdn.microsoft.com/en-us/library/ms173139.aspx
CreateInstance of a Type in another AppDomain
Simplest way to make cross-appdomain call?
Sample Application
You should just be able to copy and paste this into a new Console application. What this is doing is registering an implementation for the default AppDomain and one for the user-made AppDomains. The default simply creates a remote implementation of the interface (in the other AppDomain). Just to demonstrate the "static per AppDomain" idea, the remote implementation delegate to yet another implementation for non-default domains.
You can change implementations on the fly, all you need to change is the static class constructor (to decide what implementation to pick). Notice that you do not need to change the Main method, our calling code in this case.
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine(Parameters.GetValue(""));
Console.Read();
}
}
static class Parameters
{
private static IParameterProvider _provider;
static Parameters()
{
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
{
_provider = new ParameterProviderProxy(AppDomain.CreateDomain(Guid.NewGuid().ToString()));
}
else
{
// Breakpoint here to see the non-default AppDomain pick an implementation.
_provider = new NonDefaultParameterProvider();
}
}
public static object GetValue(string name)
{
return _provider.GetValue(name);
}
}
interface IParameterProvider
{
object GetValue(string name);
}
class CrossDomainParameterProvider : MarshalByRefObject, IParameterProvider
{
public object GetValue(string name)
{
return Parameters.GetValue(name);
}
}
class NonDefaultParameterProvider : IParameterProvider
{
public object GetValue(string name)
{
return AppDomain.CurrentDomain.FriendlyName;
}
}
class ParameterProviderProxy : IParameterProvider
{
private IParameterProvider _remoteProvider;
public ParameterProviderProxy(AppDomain containingDomain)
{
_remoteProvider = (CrossDomainParameterProvider)containingDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
typeof(CrossDomainParameterProvider).FullName);
}
public object GetValue(string name)
{
return _remoteProvider.GetValue(name);
}
}
A Note on Life Span
One of the main problems with managing a refactoring of static classes isn't usually the changing of the client code (as this is supported by lots of refactoring tools and there are techniques to get it done safely), but managing the life span of the object. Instance objects rely on living references (otherwise they are garbage collected), these can usually be made "easily accessible" by keeping one in a public static member somewhere, but usually this is what you are trying to avoid by refactoring in the first place.
It doesn't seem like you will have to worry about this concern, as you are leaving the calling code attached to the static classes, therefore the life span will remain the same.
For every static method, create an instance one. Add a static singleton variable that you can assign any implementation to. Make the static methods call the instance methods on the static singleton.
This will allow you to swap the implementation at runtime, but you can only have one implementation hooked in at the same time.
Existing code does not need to change.
Static Classes can be transformed into Singleton Objects.
Singleton Objects support interfaces.
Interfaces can be used for different implementations.
(1) Definition of Problem.
Suppose you have a class that have static members.
--
StringsClass.cs
--
namespace Libraries
{
public static class StringsClass
{
public static string UppercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to uppercase,
// and output stored in "Result"
return Result;
} // string UppercaseCopy(...)
public static string LowercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to lowercase,
// and output stored in "Result"
return Result;
} // string LowercaseCopy(...)
public static string ReverseCopy(string Value)
{
string Result = "";
// code where "Value" is reversed,
// and output stored in "Result"
return Result;
} // string ReverseCopy(...)
} // class StringsClass
} // namespace Libraries
--
And, several code that uses that static elements, from that class.
--
StringsLibraryUser.cs
--
using Libraries;
namespace MyApp
{
public class AnyClass
{
public void AnyMethod()
{
string Example = "HELLO EARTH";
string AnotherExample = StringsClass.LowercaseCopy(Example);
} // void AnyMethod(...)
} // class AnyClass
} // namespace MyApp
--
(2) Transform, first, the class, into a non static class.
--
StringsClass.cs
--
namespace Libraries
{
public class StringsClass
{
public string UppercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to uppercase,
// and output stored in "Result"
return Result;
} // string UppercaseCopy(...)
public string LowercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to lowercase,
// and output stored in "Result"
return Result;
} // string LowercaseCopy(...)
public string ReverseCopy(string Value)
{
string Result = "";
// code where "Value" is reversed,
// and output stored in "Result"
return Result;
} // string ReverseCopy(...)
} // class StringsClass
} // namespace Libraries
--
(3) Add code the allow class handle a single object.
--
StringsClass.cs
--
namespace Libraries
{
public class StringsClass
{
private static Singleton instance = null;
private Singleton()
{
// ...
}
public static synchronized Singleton getInstance()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public string UppercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to uppercase,
// and output stored in "Result"
return Result;
} // string UppercaseCopy(...)
public string LowercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to lowercase,
// and output stored in "Result"
return Result;
} // string LowercaseCopy(...)
public string ReverseCopy(string Value)
{
string Result = "";
// code where "Value" is reversed,
// and output stored in "Result"
return Result;
} // string ReverseCopy(...)
} // class StringsClass
} // namespace Libraries
--
(4) Code that calls the class, should add the reference for the singleton.
--
StringsLibraryUser.cs
--
using Libraries;
namespace MyApp
{
public class AnyClass
{
public void AnyMethod()
{
string Example = "HELLO EARTH";
string AnotherExample = StringsClass.getInstance().LowercaseCopy(Example);
} // void AnyMethod(...)
} // class AnyClass
} // namespace MyApp
--
(5) Define an interface, with similar declarations to the previous static class,
and allow the singleton, to implement that interface. Omit the singletons members, in the interface declaration
--
StringsClass.cs
--
namespace Libraries
{
public interface StringsInterface
{
string UppercaseCopy(string Value);
string LowercaseCopy(string Value);
string ReverseCopy(string Value);
} // interface StringsInterface
public class StringsClass: StringsInterface
{
private static Singleton instance = null;
private Singleton()
{
// ...
}
public static synchronized Singleton getInstance()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public string UppercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to uppercase,
// and output stored in "Result"
return Result;
} // string UppercaseCopy(...)
public string LowercaseCopy(string Value)
{
string Result = "";
// code where "Value" is converted to lowercase,
// and output stored in "Result"
return Result;
} // string LowercaseCopy(...)
public string ReverseCopy(string Value)
{
string Result = "";
// code where "Value" is reversed,
// and output stored in "Result"
return Result;
} // string ReverseCopy(...)
} // class StringsClass
} // namespace Libraries
--
(6) In the code, where your are using your singleton, the previous class that contained static methods, replace the singleton for an interface.
--
StringsLibraryUser.cs
--
using Libraries;
namespace MyApp
{
public class AnyClass
{
public StringsInterface StringsHelper = StringsClass.getInstance().LowercaseCopy(Example);
public void AnyMethod()
{
string Example = "HELLO EARTH";
string AnotherExample = StringsHelper;
} // void AnyMethod(...)
} // class AnyClass
} // namespace MyApp
--
Now, you can add other classes that support the same declarations,
with different implementation.
Cheers.
--