We have a functions library and some utility variables are stored in two diferent ways depending on the app context desktop app/website
In website we use Sessions and in desktop static variables and we would like to unite and automatize the getters//setters for those variables without affecting performance too much
Example:
public static class Cons
{
public static bool webMode;
}
public static class ConsWEB
{
public static string Username
{
get{ return HttpContext.Current.Session["username"].ToString();}
set{ HttpContext.Current.Session["username"]=value;}
}
}
public static class ConsAPP
{
private static string _username;
public static string Username
{
get{ return _username;}
set{ _username=value;}
}
}
Solution 1 we thought, using IFs (seems bad for performance, take into account accessing variables lots of times, and in some cases the variables are custom classes with complex contents):
public static class Cons
{
public static bool webMode;
public static string Username
{
get{ return webMode? ConsWEB.Username : ConsAPP.Username; }
set
{
if(webMode) { ConsWEB.Username = value; }
else { ConsAPP.Username = value; }
}
}
}
Solution 2 using delegates, at the Static Class constructor associate delegated methods to each get and set depending on the case. If is webMode point to the get/set methods of ConsWEB, otherwise to the get/set methods of ConsAPP...
Is the solution 2 the best one performance-wise? Are there other methodologies for this cases?
Neither is optimal...
First, forget about performance think design first.
You should do it through an interface or similar:
public interface IConsProvider
{
string UserName { get; set; }
}
Now your implementations (NOTE: you should not really be compiling for both desktop and web in the same assembly. System.Web, for example, is not available in Client Profile - which you should really use for desktop apps).
public class WebConsProvider : IConsProvider
{
public string UserName
{
// DON'T USE .ToString()! If it's null you get NullReferenceException!
get{ return HttpContext.Current.Session["username"] as string; }
set{ HttpContext.Current.Session["username"]=value; }
}
}
public class DefaultConsProvider : IConsProvider
{
public string UserName
{
get; set;
}
}
And then your environment static:
public static class Cons
{
//initialise to default as well - only web apps need change it
private static IConsProvider _provider = new DefaultConsProvider();
public static IConsProvider Provider
{
get { return _provider; }
set { _provider = value; /* should check for null here and throw */ }
}
//if you really want you can then wrap the properties
public static string UserName
{
get {
return _provider.UserName;
}
set {
_provider.UserName = value;
}
}
}
Now you have an extensible provider whose implementation you do not need to worry about.
I do personally also have an issue with wrapping HttpContext.Current - however in most scenarios that does work fine - if you have any asynchrony going on, however, then you have to be careful.
Also - as I mention in my comments - you no longer need to wrap the properties as statics in Cons now. Indeed you gain an awful lot of testability and extensibility by changing code like this:
public void TraceUserName()
{
Trace.WriteLine(Cons.UserName ?? "[none]");
}
To this:
public void TraceUserName(IConsProvider provider)
{
Trace.WriteLine(provider.UserName ?? "[none]");
}
Believe me there will be times in your code where you'll wish "just for this call I'd like to override the UserName - but I can't, because it's a static property".
Finally you now have another extensibility mechanism at your disposal that you don't with statics : extension methods.
Say you add a common storage mechanism to the interface for strings:
string this[string key] { get; set; }
So that's a string indexer, allowing us to implement a dictionary-like functionality for unforeseen values. Assume they've both been implemented, with a Dictionary<string, string> in the DefaultConsProvider and wrapping the Session in the WebConsProvider).
Now if I'm writing an additional module for your project that needs some additional string value - I can do this:
public static MySettingsExtensions
{
public static string GetMySetting(this IConsProvider provider)
{
//TODO: argument null checks
return provider["MySetting"];
}
public static void SetMySetting(this IConsProvider provider, string val)
{
provider["MySetting"]=val;
}
}
(Sorry had to update that last bit as for some reason I parameterised the key - which was pointless!)
That is - we can now start extending the range of strongly-typed settings offered by the provider via extension methods - without having to alter any of the original code.
Related
The following code is a valid C# construct that compile juste fine.
public class Weird : Weird.IWeird
{
private interface IWeird
{
}
}
What would be the possible uses of this?
Edit: This question is more specific that this one: "What is a private interface?". It shows that it's possible to implement a private interface from the parent type itself, which seems to be rather pointless. The only use I can think of would be a weird case of interface segregation where you would want to pass an instance of the parent class to a nested class instance as IWeird.
This is probably one of these situations in compiler development when prohibiting something has a higher cost than allowing it. Prohibiting this use would require writing and maintaining code to detect this situation, and report an error; if the feature works as-is, this is an additional work for the team, and it could be avoided. After all, perhaps someone with good imagination could figure out a way to use the feature.
As far as a useful example goes, one potential use is to make another implementation in the class, and use it as an alternative without exposing it to the users of the API:
public class Demo : Demo.Impl {
// Private interface
private interface Impl {
public bool IsValidState {get;}
void DoIt();
}
// Implementation for the error state
private class Error : Impl {
public bool IsValidState { get { return false; } }
public void DoIt() {
Console.WriteLine("Invalid state.");
}
}
private readonly string name;
// Implementation for the non-error state
public bool IsValidState { get { return true; } }
public void DoIt() {
Console.WriteLine("Hello, {0}", name);
}
// Constructor assigns impl depending on the parameter passed to it
private readonly Impl impl;
// Users are expected to use this method and property:
public bool IsValid {
get {
return impl.IsValidState;
}
}
public void SayHello() {
impl.DoIt();
}
// Constructor decides which impl to use
public Demo(string s) {
if (s == null) {
impl = new Error();
} else {
impl = this;
name = s;
}
}
}
As far as best practices go, this design is questionable at best. In particular, I would create a second nested class for the non-error implementation, rather than reusing the main class for that purpose. However, there is nothing terribly wrong with this design (apart from the fact that both IsValidState and DoIt are visible) so it was OK of the C# team to allow this use.
I have code as below
public class LocalDB
{
public static int e_SessionID;
public static string e_EventName;
public static string e_TimeCreate;
}
in other class:
public static LocalDB newEvent ;
public void something()
{
newEvent.e_SessionID=123;
}
but it is can not pass value.
Problem : You are trying to access the static feilds using instance reference variable newEvent as below:
newEvent.e_SessionID=123;
//^^^Here
Solution : You need to use classname to access the static fields
newEvent.e_SessionID=123;
//^^^Replace with classname LocalDB here
Replace this:
newEvent.e_SessionID = 123;
With this:
LocalDB.e_SessionID = 123;
Why don't you set them up as properties? Have a read of this SO post why prefer properties to public variables
"Fields are considered implementation details of classes and exposing them publicly breaks encapsulation."
public class LocalDB
{
public int SessionID { get; set; }
}
Static methods and variables can only invoke using the class name
and you are trying to call using the class object.
if you want to set the value of e_SessionID set the value using class name as follows
LocalDB.e_SessionID=123;
try to use property instead:
public class LocalDB
{
public int e_SessionID { get; set; }
public string e_EventName { get; set; }
public string e_TimeCreate { get; set; }
}
Prefer instance data to static data.
Static data is effectively global state. Do you have only one event in the lifetime of your program? What if you need to support multithreading? This is object-oriented programming; use objects.
Encapsulate data.
Avoid making fields public. Prefer properties, as others have stated. Note that this allows assigning the creation time at construction (and only then).
Use appropriate types.
If you are storing a date/time value, normally you would use the DateTime class.
Favor immutability.
If you know the values of properties at construction time, set them then and don't allow them to be changed.
Think about names.
Descriptive names matter, especially when you're doing maintenance after six months. I didn't change the name of LocalDB in my example, as I don't know your domain or use case. However, this class looks more like an event than a database to me. Would Event be a better name?
The following example uses C# 6 syntax; earlier versions would need to add private setters and move the initialization to the constructor.
public class LocalDB
{
public LocalDB(int sessionID, string eventName)
{
SessionID = sessionID;
EventName = eventName;
}
public int SessionID { get; }
public string EventName { get; }
public DateTime TimeCreate { get; } = DateTime.UtcNow;
}
public class Other
{
public void DoSomething()
{
NewEvent = new LocalDB(1, "Other Event");
}
public LocalDB NewEvent { get; private set; }
}
A flaw in this example is that the NewEvent property of an Other instance will be null on creation. Avoid nulls where possible. Perhaps this should be a collection of events; not knowing your use case I can't say.
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.
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.
--
This is probably easiest to explain with code (this is of course not the actual code but it has the same properties):
I have an interface that looks something like this:
public interface ISomeProvider
{
object GetFoo1(); //<-- This needs caching
//These others don't
object GetFoo2();
object GetFoo3();
//And let's say 20 more
}
And this has an implementation like this:
//NOTE: Sealed class otherwise we could inherit from it
public sealed class SuperCleverProvider : ISomeProvider
{
public object GetFoo1()
{
return "a";
}
public object GetFoo2()
{
return "b";
}
public object GetFoo3()
{
return "b";
}
}
Now one of these calls, let's say GetFoo1 is really heavy so I want to provider a new version of the interface where calls to it are cached using an instance of the old one.
I'm doing it like this at the moment:
public class CachedSuperCleverProvider : ISomeProvider
{
private readonly SuperCleverProvider _provider;
public CachedSuperCleverProvider(SuperCleverProvider provider)
{
_provider = provider;
}
private object UsingCache<T>(string cacheKey, Func<T> eval)
{
//Pretend this does caching. This is not related to the question
throw new NotImplementedException();
}
public object GetFoo1()
{
return UsingCache("foo1", _provider.GetFoo1);
}
//The code below this point is what I want to get rid of
public object GetFoo2()
{
return _provider.GetFoo2();
}
public object GetFoo3()
{
return _provider.GetFoo3();
}
//And so on for all the rest
}
This has two problems (at least):
Every time someone adds a method to the interface I have to go change this even though I dont want this new method to be cached
I get this huge list of useless code that just call through to the underlying implementation.
Can anyone think of a way of doing this that doesn't have these problems?
Three options:
Autogenerate the class
Use PostSharp or something similar to do it in a more interceptor-based way
Live with it
Personally I'd probably go with the third option, unless you really find yourself doing this a lot. Weigh up the cost of each option - how much time are you actually going to spend adding this delegation?
Personally I'd like to see this sort of thing as a language feature - "delegate to this interface via this field unless I override it" but obviously that's not present at the moment...
Here's what I'd suggest. It's not too much better, but will simplify the wrapping process.
Create a class SomeProviderWrapper:
public class SomeProviderWrapper : ISomeProvider
{
protected ISomeProvider WrappedProvider { get; private set; }
protected SomeProviderWrapper(ISomeProvider wrapped)
{
if (wrapped == null)
throw new ArgumentNullException("wrapped");
WrappedProvider = wrapped;
}
public virtual object GetFoo1()
{
return WrappedProvider.GetFoo1();
}
public virtual object GetFoo2()
{
return WrappedProvider.GetFoo2();
}
public virtual object GetFoo3()
{
return WrappedProvider.GetFoo3();
}
}
Now that the wrapping is relegated to its own class, you can write the caching version:
public class CachedSuperCleverProvider : SomeProviderWrapper
{
public CachedSuperCleverProvider(ISomeProvider wrapped) : base(wrapped) { }
private object UsingCache<T>(string cacheKey, Func<T> eval)
{
throw new NotImplementedException();
}
public override object GetFoo1()
{
return UsingCache("foo1", WrappedProvider.GetFoo1);
}
}
This keeps the delegation code out of your super clever provider. You will still have to maintain the delegation code, but it won't pollute the design of your caching provider.