With the use of static classes (and constant strings) I want to be able to get constant values like this:
var value = Constants.Labels.Controls.TopNavigation.Save;
I created this structure for this problem:
public static class Constants
{
public static class Labels
{
public static class Controls
{
public static class TopNavigation
{
public const string Save = "Save";
public const string Refresh = "Refresh";
}
}
public static class General
{
public static class Errors
{
public const string UnexpectedError = "An unexpected error occured.";
}
}
}
}
Now the problem is, if I define everything in it, this will grow enormously.
What is the best way to split this into different/partial classes or folder structure so that this keeps maintainable. Keep in mind... To get the value, I always want to obligate the user to start with Constants.Labels....
If possible I would also like one class-file per lowest level...
you could use either resource files or an XML file to store them as key pair.
If the class hierarchy does not provide any value other than organizing the constants, why not just use namespaces?
namespace Constants.Labels.Controls
{
public static class TopNavigation
{
public const string Save = "Save";
public const string Refresh = "Refresh";
}
}
That way you meet your objective of one class-file per lowest level.
The best solution (for now) for this problem was to work with partial classes. Disadvantage: There is some repeating structure for each file. Advantages: When the program expands, this file won't become huge. It's separated in more files AND I need to use the full name to get the correct value. So this was my preferred solution:
------------TopNavigation.cs:------------
public partial class Constants
{
public partial class Labels
{
public partial class Controls
{
public partial class TopNavigation
{
public const string Save = "LABELS_CONTROLS_TOPNAVIGATION_SAVE";
public const string New = "LABELS_CONTROLS_TOPNAVIGATION_NEW";
}
}
}
}
------------Errors.cs:------------
public partial class Constants
{
public partial class Labels
{
public partial class General
{
public partial class Errors
{
public const string Unexpected = "LABELS_GENERAL_ERRORS_UNEXPECTED";
public const string EmptyArgument = "LABELS_GENERAL_ERRORS_EMPTYARGUMENT";
}
}
}
}
If someone should post a better solution to my problem, I'll be happy to accept this as the correct answer.
using System;
namespace Test
{
public class TopNavigationConst {
private const string SAVE = "Save";
private const string REFRESH = "Refresh";
public String Save {get{return SAVE; }}
public String Refresh {get{return REFRESH;}}
}
public class ErrorsConst
{
public const string UNESPECTEDERROR = "An unexpected error occured.";
public String UnexpectedError {get{return UNESPECTEDERROR; }}
}
public class ControlsConst
{
private TopNavigationConst topNavigation = new TopNavigationConst();
public TopNavigationConst TopNavigation {get{return topNavigation;}}
}
public class GeneralConst
{
public ErrorsConst errors = new ErrorsConst();
public ErrorsConst Errors {get{return errors;}}
}
public class LabelsConst
{
public static ControlsConst controls = new ControlsConst();
public static GeneralConst general = new GeneralConst();
public ControlsConst Controls {get{return controls;}}
public GeneralConst General {get{return general;}}
}
public class Constants
{
public static LabelsConst labels = new LabelsConst();
public static LabelsConst Labels {get{return labels;}}
}
public class Test
{
public static void Main()
{
var value = Constants.Labels.Controls.TopNavigation.Save;
System.Console.WriteLine(value);
}
}
}
Related
In C# a static class can not derive from any other class besides object.
Currently I have this base class:
public static class BaseModule
{
public static string UsedSource {get; set;}
public static Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
Now, depending on which class I'm using, I want to change UsedSource.
// this does not work
internal static class ModuleA : BaseModule
{
static ModuleA(){
UsedSource = "A" // just an example
}
}
// this does not work
internal static class ModuleB : BaseModule
{
static ModuleB(){
UsedSource = "B" // just an example
}
}
Supposed to be called like this
ModuleA.Write("Hi");
ModuleB.Write("Hi");
This approach does not work because a static class cannot derive from anything else than object.
Is there any other way to change the property?
You have a lot of static classes going on here and I'm not entirely sure they're necessary. My example does not use static classes other than for the OtherStaticClass reference you have. I understand this may not be quite what you're looking for; many ways to skin this cat.
public abstract class BaseModule
{
public string UsedSource { get; set; }
public void Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
public class ModuleA : BaseModule
{
public ModuleA()
{
UsedSource = "A";
}
}
public class ModuleB : BaseModule
{
public ModuleB()
{
UsedSource = "B";
}
}
To get your output then, you just need to create new instances of ModuleA and ModuleB.
var moduleA = new ModuleA();
var moduleB = new ModuleB();
moduleA.Write("Hi");
moduleB.Write("Hi");
Using a static class means using a singleton. Singletons defeat the purpose of tracking the effective dependencies of your classes.
Anyway, you can approach the problem by refactoring your code and using a factory:
In this case, just drop the static keyword and let the class be inheritable (you have to add the appropriate virtual keywords to allow proper inheritance):
public class BaseModule
{
public string UsedSource {get; set;}
public Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
Then, add an additional class which holds the reference (I gave useless names, focus on the purpose):
public static class MySingleton
{
public static BaseModule _Module;
public static BaseModule Module
{
get
{
return _Module;
}
}
public static void ChangeImplementation (BaseModule module)
{
// do your checks here
_Module = module;
}
}
This way wou can achieve what you ask.
As you can see, this code has several issues, among them it's important to note that this code has global side effects and is not thread safe.
A better approach is to have drop the singleton entirely, and pass the BaseModule class (that can be inherited) as an argument of methods/constructors when needed.
I don't see that you need more than one static class. Instead separate the logic into methods in one static class.
public static class Module
{
private const string SourceA = "A";
private const string SourceB = "B";
public static WriteA(string text)
{
Write(SourceA, text);
}
public static WriteB(string text)
{
Write(SourceB, text);
}
private static Write(string source, string text)
{
OtherStaticClass.Log(source, text);
}
}
Then instead of
ModuleA.Write("Hi");
ModuleB.Write("Hi");
you'd do
Module.WriteA("Hi");
Module.WriteB("Hi");
If you can't change the BaseModule class, you can use it with other state and recover state after using:
public static class BaseModule
{
public static string UsedSource {get; set;}
public static Write(string text)
{
OtherStaticClass.Log(UsedSource, text);
}
}
internal class Writer : IDisposable
{
string _lastSource;
public Writer(string source)
{
_lastSource = BaseModule.UsedSource;
BaseModule.UsedSource = source;
}
public void Dispose()
{
BaseModule.UsedSource = _lastSource;
}
}
internal abstract class Module
{
public abstract Source { get; };
public void Write(string text)
{
using (var writer = new Writer(Source))
{
BaseModule.Write(text);
}
}
}
internal class ModuleA : Module
{
public override Source => "A";
}
internal class ModuleB : Module
{
public override Source => "B";
}
But you must ensure thread safety.
If you can change the BaseModule class:
public static class BaseModule
{
public static Write(string text, string source)
{
OtherStaticClass.Log(source, text);
}
}
internal abstract class Module
{
public abstract Source { get; };
public void Write(string text)
{
BaseModule.Write(text, Source);
}
}
internal class ModuleA : Module
{
public override Source => "A";
}
internal class ModuleB : Module
{
public override Source => "B";
}
I've got a class like this with some custom attributes. I'm not sure whether i actually have to implement these.
[AttributeUsage(AttributeTargets.Field)]
private class IsValue : Attribute { }
[AttributeUsage(AttributeTargets.Field)]
private class IsRep : Attribute { }
[AttributeUsage(AttributeTargets.Class)]
private class IsConstant : Attribute { }
public static class Constants
{
[IsConstant]
public static class EulerGamma
{
[IsValue]
public const double Value = 0.5772156649015;
[IsRep]
public const string Str = "γ";
}
[IsConstant]
public static class EulerNumber
{
[IsValue]
public const double Value = 2.718281828459;
[IsRep]
public const string Str = "e";
}
[IsConstant]
public static class Pi
{
[IsValue]
public const double Value = 3.1415926535898;
[IsRep]
public const string Str = "π";
}
[IsConstant]
public static class GoldenRatio
{
[IsValue]
public const double Value = 1.6180339887499;
[IsRep]
public const string Str = "φ";
}
}
Let's say this is in some class "MyMathClass", where I'd like to implement a method like this:
string ValueOrString(double x)
This method would return string representation of the constant if the number passed is equal to the constant, else it would return the original number.
So, if i passed exactly 3.1415926535898 this method would give me the string "π".
If is passed for example 2.5315621321 this would return me "2.5315621321" (string).
Would you please help me out?
I would create a class that uses a dictionary:
public static class Constants
{
static Dictionary<double, string> constantNames;
static Constants()
{
Constants.constantNames = new Dictionary<double, string>();
Constants.constantNames.Add(3.1415926535898, "π");
Constants.constantNames.Add(2.718281828459, "e");
}
public static string ValueOrString(double value)
{
if (constantNames.ContainsKey(value))
{
return constantNames[value];
}
else
{
return value.ToString();
}
}
}
When the function string ValueOrString(double value) is called, you can check if the provided value exists in the dictionary. If it exists, you retrieve the name of the constant from it. Otherwise, you return the value as a string.
I currently have the following problem:
I have a class which includes 3 different fields
Enum x
ActiveDirectoryUser y
CustomClass z
The enum can be initialised by passing a string or the enum object.
The ADUser can be initialised by passing a string (LoginName) or the user by itself and the CustomClass can be initialized by passing a string, int or the object.
Now I want to initialize the class to pass all different combinations like
class(string enumValue, string adUser, string customClass)
class(string enumValue, ADUser adUser, CustomClass customClass)
class(EnumValue enumValue, string adUser, CustomClass customClass)
Is there a way to simplify the constructors without typing all of the 12 possibilities (Enum-2 * ADUser-2 * CClass-3 = 12)?
I thought about chained constructors where i also ended up with 12 constructors but also thought about just passing the c# Object on each parameter and cast it and do stuff with it but i think that is just a dirty workaround?
Edit
The class is contained in an library and so can be used internal but also public. For the internal uses there is no problem to pass a concrete version of an object.
But if i use it public in other solutions these solutions can only refer to string or int values. So the class should be able to 'take' the values and convert them while beeing initialised because it have access to all the real objects.
Maybe this clarifies the problem a bit.
Here some code snippets with changed names:
#region Content of libraryOne
public class ClassName
{
internal EnumValueWrapper { get; set; }
internal CustomClass { get; set; }
internal ADUser { get; set; }
public ClassName() { ... } //Now via Builder Pattern
internal ClassName() { ... } //With Parameters for internal initialisations
public InformationContainer GetContentInfo()
{
//[...]Process Stuff and Return Container
}
}
internal CustomClass { ... }
internal EnumValueWrapper { ... }
internal ADUser { ... }
#endregion Content of libraryOne
If your class has only 3 properties (EnumValue, ADUser, CustomClass) then you should have only one constructor with these :class(EnumValue enumValue, ADUser adUser, CustomClass customClass). The ADUser and CustomClass should be instantiated outside of your class using their constructor which support string or int, etc;
Example:
class (EnumValue param, new ADUser(string_param), new CustomClass(int_param));
class (EnumValue param, new ADUser(ADUser_param), new CustomClass(string_param));
Edit
You can use it like I described above for internal scope and for the public part you can use and expose a factory (wrapper) class which actually can receive users and other parameters as strings or int and internally instantiate and return your class.
In addition to your snippet: Create a proxy like public class in your assembly that can be accessed from outside (from other assemblies).Make your class internal:
public class ClassNameBuilder
{
private ClassName _className;
public ClassNameBuilder(string enumValue, string user, string custom_class)
{
_className = new ClassName(EnumToString, new User(user), new CustomClass(custom_class));
}
public void CallClassNameMethod1()
{
return _className.Method1()
}
public void CallClassNameMethod2()
{
return _className.Method2()
}
}
The builder class can use whatever method you want to build the ClassName object; This way you can expose all your class methods without using multiple constructors.
I think the best thing to do is use the Builder pattern. You can even use it with derived classes.
My classes to build:
public class MyBaseClass
{
public MyBaseClass(SomeEnum enumValue, User user)
{
}
}
public class MyDerivedClass : MyBaseClass
{
public MyDerivedClass(SomeEnum enumValue, User user, CustomClass customStuff)
: base(enumValue, user)
{
}
}
Now let's add a builder class featuring an additional extension class for making things much more comfortable (it's sort of an extended Builder pattern using C# extension method wizadry):
public class MyBaseClassBuilder
{
public SomeEnum EnumValue { get; set; }
public User User { get; set; }
}
public static class MyBaseClassBuilderExtensions
{
public static T SetEnumValue<T>(this T instance, SomeEnum value)
where T : MyBaseClassBuilder
{
instance.EnumValue = value;
return instance;
}
public static T SetEnumValue<T>(this T instance, string value)
where T : MyBaseClassBuilder
{
instance.EnumValue = (SomeEnum)Enum.Parse(typeof(SomeEnum), value);
return instance;
}
public static T SetUser<T>(this T instance, User value)
where T : MyBaseClassBuilder
{
instance.User = value;
return instance;
}
public static T SetUser<T>(this T instance, string value)
where T : MyBaseClassBuilder
{
instance.User = new User(value);
return instance;
}
public static MyBaseClass Build(this MyBaseClassBuilder instance)
{
return new MyBaseClass(instance.EnumValue, instance.User);
}
}
Now let's do the same thing for our derived class:
public class MyDerivedClassBuilder : MyBaseClassBuilder
{
public CustomClass CustomStuff { get; set; }
}
public static class MyDerivedClassBuilderExtensions
{
public static T SetCustomStuff<T>(this T instance, CustomClass value)
where T : MyDerivedClassBuilder
{
instance.CustomStuff = value;
return instance;
}
public static T SetCustomStuff<T>(this T instance, string value)
where T : MyDerivedClassBuilder
{
instance.CustomStuff = new CustomClass(value);
return instance;
}
public static MyDerivedClass Build(this MyDerivedClassBuilder instance)
{
return new MyDerivedClass(instance.EnumValue, instance.User, instance.CustomStuff);
}
}
Now you can construct your instances in some fluent API style way:
static void Main(string[] args)
{
MyBaseClass baseInstance = new MyBaseClassBuilder()
.SetEnumValue("Alpha")
.SetUser("Big Duke")
.Build();
MyDerivedClass derivedInstance = new MyDerivedClassBuilder()
.SetEnumValue(SomeEnum.Bravo)
.SetUser(new User("Lt. Col. Kilgore"))
.SetCustomStuff("Smells like victory")
.Build();
}
Finally the additional types:
public enum SomeEnum
{
Alpha,
Bravo
}
public class User
{
public User(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
public class CustomClass
{
public CustomClass(string notation)
{
this.Notation = notation;
}
public string Notation { get; private set; }
}
This way you can construct instances which require many constructor arguments in a comfortable way.
I have a static Class and within it I have multiple public static attributes. I treat this class as my global class.
However now I need to treat this class as a variable so that I can pass it to a method of another class for processing..
I can't instantiate this class.. So in effect I can only assign the variables inside this class.
Is my understanding correct or am I missing something?
public static class Global
{
public const int RobotMax = 2;
// GUI sync context
public static MainForm mainForm;
public static SynchronizationContext UIContext;
// Database
public static Database DB = null;
public static string localDBName = "local.db";
public static Database localDB = null;
public static Database ChangeLogDB = null;
public static string changeLogDBName = "ChangeLog.db";
}
Let say I have a class like this, and I need to somehow keep a copy of this in another class maybe
public static class Global_bk
{
public const int RobotMax = 2;
// GUI sync context
public static MainForm mainForm;
public static SynchronizationContext UIContext;
// Database
public static Database DB = null;
public static string localDBName = "local.db";
public static Database localDB = null;
public static Database ChangeLogDB = null;
public static string changeLogDBName = "ChangeLog.db";
}
I need to copy the contents from Global to Global_bk.
And after that I need to compare the contents of the two classes in a method like
static class extentions
{
public static List<Variance> DetailedCompare<T>(T val1, T val2)
{
List<Variance> variances = new List<Variance>();
FieldInfo[] fi = val1.GetType().GetFields();
foreach (FieldInfo f in fi)
{
Variance v = new Variance();
v.Prop = f.Name;
v.valA = f.GetValue(val1);
v.valB = f.GetValue(val2);
if (!v.valA.Equals(v.valB))
variances.Add(v);
}
return variances;
}
}
class Variance
{
string _prop;
public string Prop
{
get { return _prop; }
set { _prop = value; }
}
object _valA;
public object valA
{
get { return _valA; }
set { _valA = value; }
}
object _valB;
public object valB
{
get { return _valB; }
set { _valB = value; }
}
}
So on my main form, how do I go about calling the compare method and passing the static Global class inside?
example: extentions.DetailedCompare(Global, Global_bk) ? Of course this would give me an error because I cant pass a type as a variable.
Please help me, this is driving me nuts...
How about the singleton pattern ? You can pass reference to shared interface (IDoable in exable below) and still have just one instance.
I.E.:
public interface IDoable {
int Value { get; set; }
void Foo();
}
public static class DoableWrapper {
private MyDoable : IDoable {
public int Value { get;set; }
public void Foo() {
}
}
private static IDoable s_Doable = new MyDoable();
public static IDoable Instance {
get { return s_Doable; }
}
}
Singleton is the way to go here. You can do it like this:
internal class SomeClass
{
private static SomeClass singleton;
private SomeClass(){} //yes: private constructor
public static SomeClass GetInstance()
{
return singleton ?? new SomeClass();
}
public int SomeProperty {get;set;}
public void SomeMethod()
{
//do something
}
}
The GetInstance Method will return you a SomeClass object that you can edit and pass into whatever you need.
You can access the members with classname.membername.
internal static class SomeClass
{
public static int SomeProperty {get;set;}
public static void SomeMethod()
{
//do something
}
}
static void main()
{
SomeClass.SomeProperty = 15;
SomeClass.SomeMethod();
}
The only way you are going to obtain a variable with the "class" information is using reflection. You can get a Type object for the class.
namespace Foo {
public class Bar
{
}
}
Type type = Type.GetType("Foo.Bar");
Otherwise, if you are really describing a class "instance" then use an object and simply instantiate one.
C# offers no other notation for class variables.
I am creating a project with many classes. I need to have a kind of settings class AKA module in VB that is accessible from all other classes. I want to know a method to achieve that without creating a separate settings object and passing it to each other class constructor.
Thanks
Use a static class with static fields
public static class Settings
{
public static string a = "a";
public static string b = "b";
public static bool c = true;
}
and in your other classes
if(Settings.c) ...
You can use the ConfigurationManager class. This has the bonus of working with the standard .NET config files.
As far as I know, My.Settings is a wrapper around this class.
The easiest way to accomplish this is to create a public static class. Under the covers, that's all VB does anyway.
Here is something I just did. This uses YAXLib (http://yaxlib.codeplex.com/) but you could use any serializer. I don't know how good the example is though.
public class FrameworkSettings
{
public static int ListenPort { get; set; }
public static int NumberOfOutgoingLines { get; set; }
public static void Load(FrameSettings settings)
{
ListenPort = settings.ListenPort;
NumberOfOutgoingLines = settings.NumberOfOutgoingLines;
}
}
public class FrameSettings
{
[YAXErrorIfMissed(YAXExceptionTypes.Warning, DefaultValue = 5060)]
public int ListenPort { get; set; }
[YAXErrorIfMissed(YAXExceptionTypes.Warning, DefaultValue = 5)]
public int NumberOfOutgoingLines { get; set; }
public void Save()
{
ListenPort = FrameworkSettings.ListenPort;
NumberOfOutgoingLines = FrameworkSettings.NumberOfOutgoingLines;
}
}
public class SettingsManager
{
YAXSerializer _mSerializer;
FrameSettings _mFrameSettings;
public SettingsManager()
{
_mFrameSettings = new FrameSettings();
if (!Directory.Exists("data"))
{
Directory.CreateDirectory("data");
}
}
public void LoadSettings()
{
_mSerializer = new YAXSerializer(typeof(FrameSettings),
YAXExceptionHandlingPolicies.ThrowErrorsOnly,
YAXExceptionTypes.Warning);
_mFrameSettings = (FrameSettings)_mSerializer.DeserializeFromFile("data\\settings.xml");
FrameworkSettings.Load(_mFrameSettings);
}
public void SaveSettings()
{
_mFrameSettings.Save();
_mSerializer.SerializeToFile(_mFrameSettings, "data\\settings.xml");
}
static class is one way. But config files were made to hold the settings and are more appropriate and easy to use. they are accessed using ConfigurationManager class.