Sol
Sol

Reputation: 365

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"
}

Upvotes: 0

Views: 1502

Answers (3)

fearofawhackplanet
fearofawhackplanet

Reputation: 53396

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;
}

Upvotes: 0

Fr&#233;d&#233;ric Hamidi
Fr&#233;d&#233;ric Hamidi

Reputation: 262939

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>();
}

Upvotes: 3

Michael
Michael

Reputation: 20049

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;

Upvotes: 0

Related Questions