A Job For Reflection? - c#

Greetings!
I have a class which is used like a cache:
public sealed class MyCache<T> : IDisposable
{
private ReaderWriterLockSlim theLock = new ReaderWriterLockSlim();
private Dictionary<int, T> theCache = new Dictionary<int, T>();
public void Add(int key, T value)
{
// ... logic/code to add to the dictionary
}
public void Clear()
{
theLock.EnterWriteLock();
try
{
theCache.Clear();
}
finally
{
theLock.ExitWriteLock();
}
}
}
This cache is used many times, so there are often multiple instances of this at any given time.
Example 1:
public static class SpecialPageCache
{
public static MyCache<string> SpecialPage = new MyCache<string>();
}
Example 2:
public static class DdListCache
{
public static MyCache<List<int, string>> DdlList = new MyCache<List<int, string>>();
}
And so on.
I have a service that can clear the caches on-demand, but unfortunately, each one has to be cleared like so:
private void ClearThemAll()
{
SpecialPageCache.SpecialPage.Clear();
DdListCache.DdlList.Clear();
// repeat for all other caches that may exist ...
}
How can I use reflection (or something else?) to call each cache's Clear() method without having to explcitly do it for each one like I do in the above ClearThemAll() method?

Ick. You'd have to go through all the types in the assembly that you're interested in, and check all the static fields. This is made even more interesting because it's a generic type. Your life will be simpler if you have a nongeneric base class:
public abstract class MyCache : IDisposable
{
public abstract void Clear();
}
public sealed class MyCache<T> : MyCache
{
// ...
}
Then at least it's relatively easy to detect whether the type of a particular field is a MyCache, fetch its value and call Clear on it without messing around with reflection over generic types.
This is generally a nasty problem though - are you sure you want to clear all the caches like this, without really "understanding" which caches you're clearing?

public interface ICache : IDisposable
{
void Clear();
}
public interface ICache<T> : ICache
{
}
public abstract class CacheBase<T> : ICache<T>
{
}
public sealed class SpecialPageCache : CacheBase<string>
{
internal SpecialPageCache()
{
}
}
public static class CacheFactory
{
private static List<ICache> cacheList = new List<ICache>();
public static TCache Create<TCache>()
where TCache : ICache, new()
{
var result = new TCache();
cacheList.Add(result);
return result;
}
public static void ClearAll()
{
cacheList.ForEach((c) => c.Clear());
}
}

You could store references to all of your instanced caches in a list. Then iterate same list, and call Clear on each MyCache. =)

Reflection sounds nasty. Without knowing more about your object lifetime, would the following work?
public abstract class MyCacheBase : IDisposable {
public static List<MyCache> caches = new List<MyCache>();
public MyCacheBase() {
caches.Add(this); // Add all constructed caches to the list
}
public static void ClearAllCaches() {
foreach (MyCache cache in cache) // clear all constructed
cache.Clear(); // caches in the list.
}
public void Finalize() {
Dispose();
}
public void Dispose() {
caches.Remove(this); // Remove disposed classes from the list
}
public abstract void Clear();
}
public sealed class MyCache<T> : MyCacheBase
{
// Rest of the implementation
}
(Thanks to Jon for noting the genericity. Almost missed it.)
If you want to have something like user specific caches you could add a user specific CacheFactory which would keep track of the caches created through it and its ClearAll() method would only clear those caches.

Why do you need to specifcally clear them are they using resources which need to be released ?
I'm wondering if you couldnt use the System.WeakReference so that the cache is garbarge collected as and when ?
http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

This sound really familiar to how Inversion of Control containers work. Why not just have something like a
Dictionary<Type, Dictionary<int, object>>
All of the functions would then take a type T and then use that type to look up the appopriate dictionary. One static MyCache could handle all your type and it could be disposed with one call.

If you really want to do reflection then you'd do something like this:
List<object> caches;
foreach (object obj in caches)
{
Type t = obj.GetType();
MethodInfo m = t.GetMethod("Clear");
// Object does not have a public instance method named "Clear"
if (m == null) { continue; }
m.Invoke(obj, new object[0]);
}

Related

Looking for non-lazy static constructor behavior

My project has many handler classes that derive from a common base class, and I am trying to get each of the handler classes to install themselves in a static table in the base class, and my first thought was a static constructor.
But this seems to use a super-lazy evaluation, and since I never refer to the derived classes directly (always by the handler table), this never triggers the static ctor.
Super simple stupid example:
public abstract class BlahBase
{
public static readonly Dictionary<string, BlahBase> Handlers = new();
public static BlahBase FindHandler(string name)
{
// look up in the Handlers table, return to caller
}
// other stuff
}
public class BlahFooHandler : BlahBase
{
static BlahFooHandler()
{
Handlers.Add("foo", typeof(BlahFooHandler));
}
// other stuff
}
public class BlahBarHandler : BlahBase
{
static BlahBarHandler()
{
Handlers.Add("bar", typeof(BlahBarHandler));
}
// other stuff
}
The idea is that BlahFooHandler and BlahBarHandler's static constructors would install themselves in the base Handlers table, and none of this apparently works without directly touching the derived class to trigger the static constructor. I'm trying to make this entirely dynamic.
I've spent much time looking into static constructors, and most questions revolve around lazy behavior: I want non lazy behavior.
An alternate approach is to use reflection and/or an [Attribute] on each of the handler classes, both of which I'm comfortable doing, but wonder if I'm missing an obvious language facility to achieve this.
You should create a static class with a static constructor and remove the other static constructors then in one spot add the handlers
public static class BlahHelper
{
public static readonly Dictionary<string, BlahBase> Handlers = new();
static BlahHelper
{
Handlers.Add("foo", typeof(BlahFooHandler));
Handlers.Add("bar", typeof(BlahBarHandler));
}
public static BlahBase FindHandler(string name)
{
// look up in the Handlers table, return to caller
}
// other stuff
}
public abstract class BlahBase
{
// other stuff
}
public class BlahFooHandler : BlahBase
{
// other stuff
}
public class BlahBarHandler : BlahBase
{
// other stuff
}
The first thing I did was change your code so it would compile; you declare Handlers to be a Dictionary<string, BlahBase>, but you have code like:
Handlers.Add("foo", typeof(BlahFooHandler));
Which adds Types to the dictionary, not BlahBase instances.
So, BlahBase now looks like:
public abstract class BlahBase
{
public static readonly Dictionary<string, Type> Handlers = new Dictionary<string, Type>();
public static BlahBase FindHandler(string name)
{
if (Handlers.TryGetValue(name, out var type))
{
var result = Activator.CreateInstance(type);
return result as BlahBase;
}
return null;
}
// other stuff
}
The rest of your code stays the same.
The rule for static constructors is that they get invoked some time before the first time the type is used. So, what I did is this:
BlahFooHandler unused1 = new BlahFooHandler();
BlahBarHandler unused2 = new BlahBarHandler();
var blah = BlahBase.FindHandler("BlahFooHandler");
I create a dummy instance of each of my BlahBase subclasses somewhere before I call BlahBase.FindHandler. Each of those statements fires of the appropriate static constructore. Then, you away to the races.
For what it's worth, I tried just declaring references to instances of those types:
BlahFooHandler unused1;
BlahBarHandler unused2;
It didn't invoke the static constructors.

Prevent a Class from being instantiated

Hi i want to have a class that cannot be instantiated but can be added as a static field to another class but i could not achieve it;
Here is what i've done;
public class ValueListManager
{
public static Operations myOps { get { return new Ops(); } }
}
public interface Operations
{
void Call();
}
public class Ops : Operations
{
public void Call()
{
}
}
I dont' want the Ops class to be instantiated anywhere else. Basically I want to be able to;
ValueListManager.Operations.Call();
But i dont want to be able to use the ops class like;
var ops = new Ops();
Is there a way to achieve this?
You can achieve that by declaring the Ops class as a private class within the ValueListManager class where you want to use it:
public class ValueListManager
{
private class Ops : Operations
{
public Ops()
{
}
public void Call()
{
}
}
public static Operations myOps { get { return new Ops(); } }
}
Note, that in this example based on your code, a new instance of the Ops class is created every time you access the myOps property. If you don't want that, you need to store the Ops instance in a static field once it is created and use that in the Getter of the property.
As I understand you want to instantiate this class only once and later use it.
You can use Singletone pattern, you can also use inheritance with this pattern.
public class Ops: Operations
{
private static Ops instance;
private Ops() {}
public static Ops Instance
{
get
{
if (instance == null)
{
instance = new Ops();
}
return instance;
}
}
public void Call()
{
// do something
}
}
and where you want to use it you can call its method:
Ops.Instance.Call()
If you don't want to nest your classes for some reason, and don't want to basically change anything except the Ops class itself, you could put your code into a different assembly (add a class library to your solution), and make the constructor internal:
public class ValueListManager
{
public static Operations myOps { get { return new Ops(); } }
}
public class Ops : Operations
{
internal Ops() {}
public void Call()
{
}
}
Then you'd only need to add a reference to that assembly from the one you want to use that, you'd not need to change any other code.
The constructor (thus new Ops()) can only be accessed from that assembly, code in other assemblies won't be able to new.
This is very similar to the design pattern singleton, but it is unclear from your code if you want only one instance or if you don't want to instantiate it from elsewhere?
If it is a single instance you're after the most recommended way to implement a singleton in c# is using the static constructor:
public class Single
{
private static Single instance;
private Single() { }
static Single()
{
instance = new Single();
}
public static Single Instance
{
get { return instance; }
}
}
Most other ways have (at least a theoretical) risk of threading issues.
However it should be noted that the singleton pattern (and typically extensive use of static methods) is in some contexts an indication of a bad design.

C# static interface or abstract implementation

I have a program that needs to be able to interface with multiple platforms ie read/write files, read/write database or read/write web requests. The platform interface is selected from configuration and does not change while the application is running. I have a single read/write interface class which is inherited by the platform specific classes so that this is abstracted from the rest of the program.
My problem is that I have 10 classes in my framework that will need to use this interface. Instead of making multiple instances of this class, or passing a single reference to every class, I figured it would make sense to make the interface static. Unfortunately I have just learned that Interfaces cannot have static methods, static methods cannot call non-static methods and static methods cannot be abstract.
Can anyone show me another method of approaching this situation?
Edit:
Thanks for everyone's input, here is my solution based on the example given by Patrick Hofman (thank you!)
interface TheInterface
{
void read();
void write();
}
public class X : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class Y : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class FileAccessor
{
public static TheInterface accessor;
public static TheInterface Accessor
{
get
{
if(accessor) return accessor;
}
}
}
This can be called by any class as:
static void Main(string[] args)
{
switch (Config.interface)
{
case "X":
FileAccessor.accessor = new Lazy<X>();
case "Y":
FileAccessor.accessor = new Lazy<Y>();
default:
throw new Lazy<Exception>("Unknown interface: " + Config.interface);
}
FileAccessor.Accessor.read();
}
Indeed, interfaces, or abstract classes can't be static themselves, but the further implementation can. Also, you can use the singleton pattern to make your life easier, and allow inheritance, etc.
public class X : ISomeInterface
{
private X() { }
public static X instance;
public static X Instance
{
get
{
return instance ?? (instance = new X());
}
}
}
Or, using Lazy<T>:
public class X : ISomeInterface
{
private X() { }
public static Lazy<X> instanceLazy = new Lazy<X>(() => new X());
public static X Instance
{
get
{
return instance.Value;
}
}
}
Disclaimer: I am the author of the library described below.
I don't know if this helps you, but I have written a library (very early version yet) that allows you to define static interfaces, by defining normal interfaces and decorating their methods with an attribute named [Static], for example:
public interface IYourInterface
{
[Static]
void DoTheThing();
}
(Note that you don't explicitly add this interface to your implementations.)
Once you have defined the interface, you can instantiate it from within your code with any valid implementation you choose:
return typeof(YourImplementation).ToStaticContract<IYourInterface>();
If the methods can't be found in YourImplementation, this call fails at runtime with an exception.
If the methods are found and this call is successful, then the client code can polymorphically call your static methods like this:
IYourInterface proxy = GetAnImplementation();
proxy.DoTheThing();
You can make a Static Class which has Variable of your Interface.
public static class StaticClass
{
public static ISomeInterface Interface;
}
Now you can access the Instance from everywhere in your Framwork
static void Main(string[] args)
{
StaticClass.Interface = new SomeClass();
}

Need a really static field in a generic class, or otherwise how to protect its visibility?

I want to have a class like:
public class Forest<S, T>
{
static IList<Animal> coolGuys = new List<Animal>();
}
But I want coolGuys to be really static, which means it has to be unique through the entire lifetime of the application. And right now its not. MS discourages this pattern, ReSharper warns, but how does one really achieve what I want?
May be I will have to do more work by creating another static class and have a public static field there or a public instance field in another singleton class. Its ok to have a redundant public class to hold just a static field, but the thing I want to avoid is the field being public/internal. I mean coolGuys is just meant for Forest<,>, why expose the incoherent things to outside world.
public class Forest
{
public static IList<Animal> coolGuys = new List<Animal>(); //want to avoid
}
public class Forest<S, T>
{
Forest.coolGuys.Add(cutie);
}
Any better pattern?
Approach 1 - Inject a State Provider
Create a type to store data.
Abstract it with an interface, so you can inject a different provider if desired (e.g. for testing).
Consuming class doesn't care about the implementation, other than it guarantees statefulness.
Concurrent dictionary takes care of thread safety.
public interface IStateProvider
{
void Store( string key, object value );
object Get( string key );
}
public class StateProvider : IStateProvider
{
private static ConcurrentDictionary<string, object> _storage = new ConcurrentDictionary<string, object>();
public void Store( string key, object value )
{
// add to storage
}
public object Get( string key )
{
// get from storage
}
}
public class Forest<T1, T2>
{
private IStateProvider _stateProvider;
public Forest( IStateProvider stateProvider )
{
_stateProvider = stateProvider;
}
public void Foo()
{
// do something with the stateful value
}
}
// of course, you could do this with a DI framework
var stateProvider = new StateProvider();
var forest = new Forest<Foo, Bar>( stateProvider );
Approach 2 - Base Class
This approach is less elegant but a bit more straightforward.
public abstract class ForestBase
{
private static List<object> _staticList = new List<object>();
protected List<object> StaticList
{
get { return _staticList; }
}
}
public class Forest<T1, T2> : ForestBase
{
public void Foo()
{
StaticList.Add( 12345 );
}
}
This hides internal data and should give you only one single instance of the static list, versus one instance per combination of generic arguments.

Is it possible to make an object expose the interface of an type parameter?

In C#, is it possible to write something like this:
public class MyClass<T> : T
where T : class, new()
{
}
I know that the above implementation does not compile, but what I am actually trying to achive is implementing some kind of generic wrapper to an unknown type, so that an client can call the wrapper just as he would call the type, provided by the parameter T, instead of calling it using something like wrapper.Instance.SomeMember().
Thanks in advance!
This isn't possible.
In my opinion, I don't think that a wrapper should be implemented using inheritance.
For example, let's say we've an Engine class and you need to implement a FerrariEngine. And you have a Car class.
You're saying that Car should inherit FerrariEngine. It looks terrible for me!
At the end of the day, you're looking to do something like dependency injection using inheritance and, again, this isn't the right path.
My suggestion is don't try to make your life easier: decide an architecture based on rational points.
UPDATE
The OP said in some comment:
I want to make this class to manage instances of objects of type T, so
that the client does not need to take care of when the instances need
to be created.
You don't need to make strange things to get what you want:
public interface IEngine
{
void Start();
}
public sealed class FerrariEngine : IEngine
{
public FerrariEngine()
{
Start();
}
public void Start()
{
}
}
public abstract class Car<TEngine> where TEngine: IEngine, new()
{
public Car()
{
_engine = new Lazy<TEngine>(() => new TEngine());
}
private readonly Lazy<TEngine> _engine;
public TEngine Engine
{
get { return _engine.Value; }
}
}
public class FerrariCar : Car<FerrariEngine>
{
}
Finally, if we create an instance of FerrariCar:
Car<FerrariEngine> myFerrari = new FerrariCar();
The engine will be instantiated and started, without developer intervention!
Check how Lazy<T> and basic generic constraints make the job ;)
In summary:
Using Lazy<T> the engine will be instantiated only when some access the Engine property.
Once the lazy-loaded engine is instantiated, since FerrariEngine implements a parameterless constructor calling Start() itself, it will start the engine.
I believe that this sample illustrates you how you can get what you're looking for and using C# "as is"!
You could have a look at DynamicObject and do something like this:
class Foo<T> : DynamicObject
{
private T _instance;
public Foo(T instance)
{
_instance = instance;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var member = typeof(T).GetProperty(binder.Name);
if (_instance != null &&
member.CanWrite &&
value.GetType() == member.PropertyType)
{
member.SetValue(_instance, value, null);
return true;
}
return false;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var member = typeof(T).GetProperty(binder.Name);
if (_instance != null &&
member.CanRead)
{
result = member.GetValue(_instance, null);
return true;
}
result = null;
return false;
}
}
class Bar
{
public int SomeProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
var bar = new Bar();
dynamic thing = new Foo<Bar>(bar);
thing.SomeProperty = 42;
Console.WriteLine(thing.SomeProperty);
Console.ReadLine();
}
}

Categories