Is there a nice way to set a constant to be that of a classes namespace?
namespace ACMECompany.ACMEApp.Services
{
public class MyService
{
private const string WhatWeDo = "ACMECompany.ACMEApp.Services";
private const string WouldBeNice = typeof(MyService).Namespace;
...
}
}
So that if the class if moved to another namespace we don't need to worry about these constants.
More Info
The constant is only really used for logging - where it is passed to some log method. This is all legacy code so wont be changing in the short term. I am aware of runtime ways to get this information such as This Question
We're using .NET 4 but will be upgrading soon to .NET 4.5.
You're not going to set a constant variable with a non-constant value. This is understandable, isn't it?
BTW, C# has the readonly keyword, to turn any class field to work like a constant once object construction time ends. They can or can't be static:
public class MyService
{
static MyService()
{
WouldBeNice = typeof(MyService).Namespace;
}
private static readonly string WouldBeNice;
}
or...
public class MyService
{
private static readonly string WouldBeNice = typeof(MyService).Namespace;
}
Also, you can achieve the same behavior using read-only properties:
// Prior to C# 6...
public class MyService
{
private static string WouldBeNice { get { return typeof(MyService).Namespace; } }
}
// Now using C# 6...
public class MyService
{
private static string WouldBeNice => typeof(MyService).Namespace;
}
// Also using C# 6...
public class MyService
{
// This can be even better, because this sets the namespace
// to the auto-generated backing class field created during compile-time
private static string WouldBeNice { get; } = typeof(MyService).Namespace;
}
Related
I have quite a sizeable static constructor for one of my classes, and was wanting to refactor it to encapsulate various bits of the initialization within static functions.
One of the things this static constructor does a lot of is initialize the values of static readonly fields. However, when I try to move these parts into functions, obviously the compiler wont let me as these can only be set in the static constructor. This makes sense as it doesn't know that I only intend to call these functions from my static constructor.
Is there any way around this? e.g. is there some sort of attribute I can put on the functions to tell the compiler the functions are only to be called from the static constructor?
You can define local functions inside a static constructor;
public class MyClass {
public static readonly int Value;
static MyClass(){
Value = Calc(1);
return;
int Calc(int a) => a;
}
}
The C# compiler will turn those local functions into static methods, with unpronounceable names.
You can do it with static and private keywords
using System;
public class User {
public static readonly string Name;
static User(){
Name = GetName();
}
//`private` function to only be called in static class itself
private static string GetName() {
return "Testing";
}
}
public class Program
{
public static void Main()
{
Console.WriteLine(User.Name);
}
}
A side note for this solution is that it can help you to prevent outsider functions' calls but cannot prevent being called internally by inner functions.
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");
}
}
}
This seems like an odd request, I appreciate that, but this is the situation:
I have a program which depends on reading in a handful of files. These files are named like: foo_bar_BAZ.txt where BAZ is the name of the project and not known until run-time. However it will not change for the entire execution of the program.
I want to have an enumerated list of strings which stores all the filenames. So far I have used a sealed class like so:
public sealed class SQLFile
{
private readonly String name;
private readonly String value;
public static readonly SQLFile CrByAuthors = new SQLFile("Changes_CR_By_Authors_%project_name%.txt", "CrByAuthors");
public static readonly SQLFile DocumentCrMetrics = new SQLFile("Changes_Document_CR_Output_%project_name%.txt", "DocumentCrMetrics");
[...]
private SQLFile(String value, String name)
{
this.name = name;
this.value = value;
}
public String ToString(string projectName)
{
return this.value.Replace("%project_name%", projectName);
}
}
As you can see this depends on my providing the project name variable every time I want to access the filename, even though that filename is really constant from the very beginning of run-time till the end.
Is there a more elegant way to handle with this situation?
A simple solution would be to have a static class with a ProjectName property. The value of this property is set during startup of the application. Your class then can use that property.
Add a static property to SQLFile, something like
public sealed class SQLFile
{
//...
private static string sProjectName;
public static string ProjectName
{
get
{
return sProjectName;
}
set
{
//optionally, you could prevent updates with:
//if (string.IsNullOrEmpty(sProjectName))
sProjectName= value;
//else throw Exception("ProjectName was already set!");
}
}
[Edit - I read the code a bit too fast, so this is what I actually meant:]
The purpose of the (poorly named IMHO) method ToString is to return the name of a file corresponding to a certain project name. There is nothing wrong with that, although it may be a responsibility which might belong to a separated class.
You could, for example, refactor the code to express its intention more clearly:
interface ISqlFileNameProvider
{
string SqlFilename { get; }
}
Then have a simple ("poor man's") implementation:
public class SimpleSqlFileNameProvider : ISqlFileNameProvider
{
private readonly string _filename;
public SimpleSqlFileNameProvider(string filename)
{
_filename = filename;
}
public string SqlFilename
{
get { return _filename; }
}
}
And then derive specialized implementation from here:
public class TemplateSqlFileNameProvider : SimpleSqlFileNameProvider
{
public TemplateSqlFileNameProvider(string template, string projectName)
: base(template.Replace("%project_name%", projectName))
{ }
}
public class CrByAuthorsFileNameProvider : TemplateSqlFileNameProvider
{
public CrByAuthorsFileNameProvider(string projectName)
: base("Changes_CR_By_Authors_%project_name%.txt", projectName)
{ }
}
public class DocumentCrMetricsFileNameProvider : TemplateSqlFileNameProvider
{
public DocumentCrMetricsFileNameProvider(string projectName)
: base("Changes_Document_CR_Output_%project_name%.txt", projectName)
{ }
}
First, note that projectName remains the parameter for the constructor of these specialized classes. There are no globals here. Next, even though you've added a bit of plumbing code to your project, it's easier to decouple your classes for simpler testing: you can create a mocked implementation of ISqlFileNameProvider and return whatever you like to test the rest of the functionality without writing to real data files.
I would certainly advise against using a global property. The fact that you can specify the project name as a constructor parameter means that you can easily test that your class behaves the way you want it to. And even though you think that it will change during project lifetime, you can easily encounter a scenario where you temporarily need to switch the project name in runtime. I would advise against using globals.
In my Application a have a set of Data Providers and Redis Cache.
Each execution different providers are used, but they all store own Data in Redis:
hset ProviderOne Data "..."
hset ProviderTwo Data "..."
I would like have one method That will delete Data for all providers that are present in code.
del ProviderOne
del ProviderTwo
I have made next code:
void Main()
{
// Both providers have static field Hash with default value.
// I expected that static fields should be initialized when application starts,
// then initialization will call CacheRepository.Register<T>() method
// and all classes will register them self in CacheRepository.RegisteredHashes.
// But code start working only when i created this classes (at least once)
// new ProviderOne();
// new ProviderTwo();
CacheRepository.Reset();
}
public abstract class AbstractProvider
{
//...
}
public class ProviderOne : AbstractProvider
{
public static readonly string Hash =
CacheRepository.Register<ProviderOne>();
//...
}
public class ProviderTwo : AbstractProvider
{
public static readonly string Hash =
CacheRepository.Register<ProviderTwo>();
//...
}
public class CacheRepository
{
protected static Lazy<CacheRepository> LazyInstance = new Lazy<CacheRepository>();
public static CacheRepository Instance
{
get { return LazyInstance.Value; }
}
public ConcurrentBag<string> RegisteredHashes = new ConcurrentBag<string>();
public static string Register<T>()
{
string hash = typeof(T).Name;
if (!Instance.RegisteredHashes.Contains(hash))
{
Instance.RegisteredHashes.Add(hash);
}
return hash;
}
public static void Reset()
{
foreach (string registeredHash in Instance.RegisteredHashes)
{
Instance.Reset(registeredHash);
}
}
protected void Reset(string hash);
}
interface IData{}
interface IDataProvider
{
string GetRedisHash();
IData GetData();
}
intefrace IRedisRepository
{
}
How make it working?
You can just access any static method/property of your class - i.e. Provider1.Name:
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(Provider1.Name + Provider2.Name);
Console.ReadLine();
}
}
In C# static constructor (one that initializes all static fields) is called only if any method of type is used as covered in C# specification 10.11 Static constructors:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
•An instance of the class is created.
•Any of the static members of the class are referenced.
Note that magical registration is very hard to write unit tests for - so while your approach would work it may be better to use some known system that allow registering objects that is convenient to test.
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.
--