在运行时以未知类型实例化自定义类

时间:2011-01-28 10:43:39

标签: c# .net

之前我看过这个问题的变种,但还没有找到答案。

我有一个自定义类:

public class Indicator
{
   public double Value { get; set;}

   virtual public void Calc(val1, val2) {}
}

我有很多来自它的类,例如:

class calc_sum : Indicator
{    
   override public void Calc(val1, val2)
   {
     Value=val1+val2;
   }
}

最后,我有一个班级来举行所有“指标”:

class IndicatorCollection
{
  List<Indicator> _collection = new List<Indicator>();

  ...Some other methods here...
}

我需要的是在“IndicatorCollection”类中提供一个方法,该方法接受从“Indicator”派生的类的基于字符串的名称,并将其添加到_collection。 即:

IndicatorCollection.AddIndicator("calc_sum");

这样用户可以在运行时添加指标(IndicatorsCollection被绑定到显示每个成员的Value属性的列表)。

我希望我足够清楚并且我采取了正确的方法。 谢谢大家

更新 Activator方法正是我想要的,所以我会试着让它更难:

添加指标实例后,可以使用IndicatorCollection公开一个新属性,该属性是类的Value属性的快捷方式。

即:

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

3 个答案:

答案 0 :(得分:3)

如果Indicator类及其后代公开了一个公共无参数构造函数,则可以使用Activator.CreateInstance()在运行时从其名称动态实例化一个类:

public class IndicatorCollection
{
    public void AddIndicator(string className)
    {
        _collection.Add((Indicator)
            Activator.CreateInstance(null, className).Unwrap());
    }

    private List<Indicator> _collection = new List<Indicator>();
}

答案 1 :(得分:0)

您可以使用激活器类根据类名实例化对象。假设bin目录(或其他探测路径)中的程序集中存在calc_sum指示符,您可以获取它的实例:

var myIndicator = Activator.CreateInstance(Type.GetType("calc_sum")) as Indicator;

答案 2 :(得分:0)

关于第二个要求(更新后),为什么不使用Dictionary<string, Inidicator>代替List<indicator>来存储名称?也许你已经过度复杂化了你的要求。

public class IndicatorCollection
{
    var _dictionary = new Dictrionary<string, Indicator>();

    public void AddIndicator(string className)
    {
        _dictionary.Add(
            className,
            (Indicator)Activator.CreateInstance(null, className).Unwrap()
        );
    }
}

然后......

public double GetValue(string indicatorName)
{
   return _dictionary[indicatorName].Value;
}