How to cache static data for classes with use of inheritance? - c#

Imagine you're making a game object that is using some texture:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public static Texture2D cursor { get { return ResourceManager.loadTexture(ref cursorTex, HoverCursor); } }
}
The loadTexture function will load the texture if null is passed. otherwise, it just returns the original value.
As you can see, I'm making an Action prototype. There will be actions like Attack, Move or Build. I want to store one (and different) texture object per class definition. This object shall be lazy-loaded when needed using the getter above.
Since the static property can't be overriden, how can I implement this for all children instances?
Here's the loadTexture:
public static Texture2D loadTexture(ref Texture2D target, string name)
{
if (target == null)
{
target = (Texture2D)Resources.Load(name, typeof(Texture2D));
}
return target;
}

You can use inheritance and polymorphism with instance members, and use a static factory method as a façade to simplify the instantiation of the implementation.
For example
public abstract class Action
{
public abstract void LoadTexture(...);
}
// Since static façade class has a generic type parameter, we're talking
// about a completely different class than just "Action" and both can co-exist!
public static class Action<TAction> where TAction : Action, new()
{
public static Texture2D LoadTexture(...)
{
// Since generic TAction parameter must implement a public parameterless
// constructor, you may instantiate T like a concrete class:
return new TAction().LoadTexture(...);
}
}
Thus, you would use the static method as follows:
Texture2D texture = Action<CustomAction>.LoadTexture2D(...);

You've practically answered the question yourself:
Since the static property can't be overriden, how can I implement this for all children instances?
Just make the property an instance property. For example:
public class Action {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/select";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public virtual Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
public class Attack {
//This two can (must) be overriden
public const string _HoverCursor = "Textures/cursors/attack";
public virtual string HoverCursor { get { return _HoverCursor; } }
//This is the get texture by string
private static Texture2D cursorTex = null;
public override Texture2D cursor
{
get
{
return ResourceManager.loadTexture(ref cursorTex, HoverCursor);
}
}
}
You would still save just one texture per class, but given an instance of each class you'll be able to retrieve the correct cursor texture for that class. Presumably you need to set the cursor only when there's an instance of the class around anyway, so this shouldn't be an unreasonable limitation.
Note in the above that if no other code actually needs the HoverCursor property, you can get rid of it, make the _HoverCursor const a private member, and then use that directly in the cursor property getter.
Also note that this implementation isn't thread-safe. As long as you're always accessing the cursor property from a single thread, that's fine. But if not (or perhaps just for the simplicity) you may prefer using the Lazy<T> class. For example:
//This is the get texture by string
private static Lazy<Texture2D> cursorTex =
new Lazy<Texture2D>(() => ResourceManager.loadTexture(HoverCursor));
public virtual Texture2D cursor
{
get
{
return cursorTex.Value;
}
}
In this version, note that the loadTexture() method has changed to always load the texture, and thus does not need the ref parameter. The Lazy<T> class will ensure thread-safe lazy initialization, calling loadTexture() only once per class.

Related

Making static class data serializable

Consider the following:
public class myClass : MonoBehaviour
{
public int i; //<- value set from inspector
static myClass()
{
Awake();
}
private static void Awake()
{
Debug.Log(i); //<- Error CS0120
}
}
This would throw me an error error CS0120: An object reference is required for the non-static field, method, or property 'myClass.i'
I could then (according to this page) try to write it in another way:
public class myClass : MonoBehaviour
{
public int i;
static myClass()
{
Awake();
}
private static void Awake()
{
var mc = new myClass();
Debug.Log(mc.i); //<- NullReferenceException
}
}
But that would throw me error NullReferenceException: Object reference not set to an instance of an object myClass.Awake ().
Meaning that I cannot serialize static variables? Is there a workaround? I'm sorry but I'm still getting used to C# and if you could also give me a brief theoretical reason why it doesn't work it would help me greatly in understanding. Thanks!
First of all: Your issue has nothing to do with a field being serializable or not.
It is rather related to your instanced class field i not being accessible from a static context. As the error states you would need an instance of your class in order to access it there but
As also mentioned classes of type MonoBehaviour are not allowed to have any constructor and may not be instanciated via the new keyword in Unity. The only allowed ways of creating instances of components is via Instantiate, AddComponent or via the constructor of e.g. new GameObject("someName", typeof(YOUR_COMPONENT));.
You don't need a Singleton for what you want. It sounds like you actually would want to go this way round:
public class myClass : MonoBehaviour
{
// This one you set via the Inspector
[SerializeField] private int _i;
// This is now a read-only property
// That can only be set by this class
public static int i { get; private set; }
private void Awake()
{
// Your instance can always access its static fields
// So this way you can assign the value
i = _i;
}
}
In general we would need more input in order to figure out your actual usecase here. It is also possible that you could rather use an entirely static class like e.g.
public static class myClass
{
public static int i = 42;
}
this makes your field not serialized but simply accessible from everywhere without the need of an instance in the Scene. You would simply access it from another MonoBehaviour like e.g.
public class Example : MonoBehaviour
{
private void Start()
{
Debug.Log(myClass.i);
}
}
Or you might want to make your class not static at all but rather access it through the correct reference like
[Serializable]
public class myClass
{
public int i = 42;
}
public class Example : MonoBehaviour
{
// Since it is tagged Serializable and now serialized in the Inspector
// an instance is created for this field automatically
[SerializedField] private myclass _myClass;
private void Awake()
{
Debug.Log(_myclass.i);
}
}
Unity can only serialize a specific instance of an class (monobehaviour). Static information is shared between all instances of the class and thus cannot be serialized by unity.
Additionally, do not put a constructor in your monobehaviours, the object is constructed by the unity engine using its own process and the awake function is called automatically. You're getting that null reference exception because the awake function is being called from your constructor and not from unities internal functions that are supposed to be initializing it, so things that need to be set up for it haven't been.
You haven't said why you need static information serialized but if you're trying to use a singleton approach there are a couple simple methods for doing it in unity:
class MySingleton : MonoBehaviour
{
[SerializeField] private int someDataA;
[SerializeField] private int someDataB;
public static MySingleton Instance
{
get;
private set;
}
public int SomeDataA
{
get
{
return someDataA;
}
set
{
someDataA = value;
}
}
public int SomeDataB
{
get
{
return someDataB;
}
set
{
someDataB = value;
}
}
private void Awake()
{
Instance = this;
}
}
alternatively
class MySingleton : MonoBehaviour
{
[SerializeField] private int someDataA;
[SerializeField] private int someDataB;
private static MySingleton instance;
public static int SomeDataA
{
get
{
return instance.someDataA;
}
set
{
instance.someDataA = value;
}
}
public static int SomeDataB
{
get
{
return instance.someDataB;
}
set
{
instance.someDataB = value;
}
}
private void Awake()
{
instance = this;
}
}
In the first example you can access the current instance of the component by going MySingleton.Instance and access your properties and functions on it. In the second example the instance is kept private and all the properties and functions are made static so you can access them directly on MySingleton without needing to see the instance.

Automatically create a copy of a static variable for each derived class

I have a base class with a static variable. I want to create derived subclasses which will automatically have their own unshared static variable. Ideally it would look like this:
class Parent
{
Texture2D picture;
static Texture2D pictureOrigin;
Parent()
{
picture = pictureOrigin;
/*Loading the static origin to an instance variable
because I might want to have more pictureOrigins
and alternate them or perhaps change the picture
of the instance based on a certain event, etc.*/
}
}
class Subclass1 : Parent
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Subclass1.pictureOrigin = Load("pictureForSubclass1");
Subclass2.pictureOrigin = Load("pictureForSubclass2");
//Then creating instances of the classes and drawing them, etc.
}
But what happens is that they all get the last loaded image (pictureForSubclass2) because the static variable pictureOrigin is shared between them.
The quickest fix is manually adding new static variable pictureOrigin to each subclass and hiding the pictureOrigin variable of the base class:
class Subclass1 : Parent
{
new static Texture2D pictureOrigin;
Subclass1() : base()
{
picture = pictureOrigin;
}
}
Alternatively, creating abstract methods or similar to ensure the creation of the new static variable in the subclasses. But it seems like too much of a hassle and not too elegant. Is there a better way of doing this?
Your question smells like a poor design. Static variables are generally poor practice in my opinion, and proper object-oriented design can eliminate the need to ever use static members.
Try refactoring like so:
public class Parent
{
private Texture2D texture;
public Parent(Texture2D texture) {
this.texture = texture;
}
public Texture2D Picture { get {
return texture;
}
}
}
public class SubClass1 : Parent
{
public SubClass1(Texture2D texture) : base(texture) {
}
}
Let me elaborate on why static is a poor choice:
Your class is now only good for a single bitmap. Eliminates the possibility to reuse a class for several bitmaps (this is the limitation you're fighting against)
Your class is not in a valid state until the static setter is called. Generally objects, once constructed, should be in a valid state. It won't be obvious to others if they're using your object that they have to statically set the bitmap on the class.
Breaks the natural garbage collection. For example if you wanted the Texture2D object to be garbage collected when all the instances of SubClass are collected it wouldn't work with your static design. Alternatively, if you use a oop design (like suggested) you have the flexibility to garbage collect or not depending on your use cases.
Makes threading more complicated. Statics are global, so you need global mutexes to guarantee thread-safety.
Makes testing more difficult. If you want to unit test the class, you have to make sure that the static is cleaned up after every test, and you couldn't run two unit tests against this class in parallel.
Makes memory management inflexible. If you use object-oriented design you can choose to share bitmaps among all instances, or allocate a new bitmap for every instance.
You can do this with a static Dictionary<Type,Texture2D>.
public class Parent
{
// Keep a table of types and default values
protected static Dictionary<Type, Texture2D> pictureOrigin;
static Parent()
{
// static ctor. initialize table
pictureOrigin=new Dictionary<Type, Texture2D>();
}
internal static void SetDefaultPicture<T>(Texture2D picture)
{
// Set default based on type T
Type type=typeof(T);
pictureOrigin[type]=picture;
}
public Parent()
{
// Assign default based on this type
Picture=pictureOrigin[this.GetType()];
}
public Texture2D Picture { get; set; }
}
public class SubClass1 : Parent
{
}
public class SubClass2 : Parent
{
}
to be used as
static void Main(string[] args)
{
Texture2D picture0 = Load("pictureForParent");
Texture2D picture1=Load("pictureFroSubClass1");
Texture2D picture2=Load("pictureFroSubClass2");
Parent.SetDefaultPicture<Parent>(picture0);
Parent.SetDefaultPicture<SubClass1>(picture1);
Parent.SetDefaultPicture<SubClass2>(picture2);
}
Here is the debug of an example. It shows that SubClass1 initialized with pictureForSubClass1 automatically.
A static member that declared in generic type is basically declared per class and its generic.
For example Foo<Bar>.baz is not equal to Foo<Qux>.baz.
So basically you can do this:
abstract class Parent<T>
{
Texture2D picture;
static Texture2D pictureOrigin;
Parent()
{
picture = pictureOrigin;
/*Loading the static origin to an instance variable
because I might want to have more pictureOrigins
and alternate them or perhaps change the picture
of the instance based on a certain event, etc.*/
}
}
class Parent : Parent<Parent>
{
Parent () : base()
{ }
}
class Subclass1 : Parent<Subclass1>
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent<Subclass2>
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Parent<Subclass1>.pictureOrigin = Load("pictureForSubclass1");
Parent<Subclass2>.pictureOrigin = Load("pictureForSubclass2");
}

Refactoring a static class to separate its interface from implementation

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.
--

Static image variable across multiple classes

I'm currently working in C#, and I have a base class (bullet) that is required to have a variable and subsequent getter (image) because another class expects that behavior (powerup) in order to display properly. Bullet will then be extended to make many different bullets with varying behavior. however, every bullet extension class needs only one image per class (not per instance) because it will never need to change between bullets of similar class, and there will be hundreds of them on screen, so space is an issue. ie, I need an object in a base class, that is then static in extensions from that class. Is there any way to create this in C#, and if not, out of curiosity, any other object oriented language?
Many Thanks
edit:
for example:
class bullet{
public Image Level
{
get { return image; }
set { image = value; }
}
}
class spiralBullet : bullet{
static var image = "spiralbullet";
}
class largeBullet : bullet{
static var image = "largebullet";
}
except somehow, the getter returns the correct static image for each class
Define an abstract property Getter on your base class.
In the derived class, have a private static Image field.
Override the abstract property Getter and return your static image field.
public abstract class Bullet
{
public abstract Image Image { get; }
}
public class SquareBullet : Bullet
{
private static Image _image /* = Load your image */;
public override Image Image
{
get
{
return _image;
}
}
}
Alternatively, if the Image is a simple hard-coded value:
public abstract class Bullet
{
public abstract string Image { get; }
}
public class SquareBullet : Bullet
{
public override Image Image
{
get
{
return "Square";
}
}
}
The advantage here, if it's suitable, is that the value "Square" exists in a code segment, not a data segment, and is 'static' (or shared) by definition.

Instantiating custom classes at runtime of unknown type

I saw variants of this question before, but didn't find answer yet.
I have a custom class:
public class Indicator
{
public double Value { get; set;}
virtual public void Calc(val1, val2) {}
}
And I have many classes derived from it, such as:
class calc_sum : Indicator
{
override public void Calc(val1, val2)
{
Value=val1+val2;
}
}
Finally, I have a class to hold all "Indicators":
class IndicatorCollection
{
List<Indicator> _collection = new List<Indicator>();
...Some other methods here...
}
What I need, is to provide a method in the "IndicatorCollection" class which accepts a string based name of a class derived from "Indicator" and add it to the _collection.
i.e:
IndicatorCollection.AddIndicator("calc_sum");
That way the user can add indicators at runtime (The IndicatorsCollection is binded to a list which displays the Value property of each member).
I hope I was clear enough and that I am taking the right approach.
Thank you all
Update:
The Activator method is exactly what I was looking for, So I'll try to make it more difficult:
After adding the Indicator instance, can IndicatorCollection expose a new Property which is a shortcut to the class's Value property.
i.e:
// After adding calc_sum to the collection, The IndicatorCollection class will have the following //property:
public double calc_sum
{
get { return _collection.Find(i=>i.name=="calc_sym").First().Value;
// The indicator class also has a public member of "name"
}
If the Indicator class and its descendants expose a public parameterless constructor, you can use Activator.CreateInstance() to dynamically instantiate a class from its name at runtime:
public class IndicatorCollection
{
public void AddIndicator(string className)
{
_collection.Add((Indicator)
Activator.CreateInstance(null, className).Unwrap());
}
private List<Indicator> _collection = new List<Indicator>();
}
You can use the activator class to instantiate objects based on class name. Assuming the calc_sum indicator exists in an assembly in the bin directory (or other probing paths), you can get an instance of it:
var myIndicator = Activator.CreateInstance(Type.GetType("calc_sum")) as Indicator;
Regarding the second requirement (after your update), why not use a Dictionary<string, Inidicator> instead of List<indicator> to store the names? Maybe you are over complicating your requirements.
public class IndicatorCollection
{
var _dictionary = new Dictrionary<string, Indicator>();
public void AddIndicator(string className)
{
_dictionary.Add(
className,
(Indicator)Activator.CreateInstance(null, className).Unwrap()
);
}
}
and then...
public double GetValue(string indicatorName)
{
return _dictionary[indicatorName].Value;
}

Categories

Resources