实例化实现通用接口的类

时间:2015-06-08 12:17:38

标签: c# reflection

我有一个用于指定GetData方法的接口,该方法通过其ID

返回该类的一个实例
public interface ILabelData<T> {
  T GetData(object id);
}

并且还有很多不同的类实现接口并且当然有成员:

public class BTAC : ILabelData<BTAC> {
  // members...
  // and interface impl:
  public BTAC GetData(object id) {
    return null;
  }
}
public class KTAC : ILabelData<KTAC> {
  // members...
  // and interface impl:
  public KTAC GetData(object id) {
    return null;
  }
}

在调用方法中,我想实例化一个BTAC / KTAC / ...类并调用它们的GetData方法。 (之后的目的是因为我有了所需的实例后我想得到它的成员和属性。获取成员和属性不是我的问题的一部分。)

ILabelData<object> o = Activator.CreateInstance(type, new object[] { myID });
^^^^^^^^^^^^^^^^^^^^
object data = o.GetData(myID);

问题是编译错误无法隐式转换类型&#39;对象&#39;到&#39; ILabelData&lt;对象&gt;&#39;

在实例化正确的课程后,我确实需要成员和属性,所以它不足以取回ILabelData类型的对象。

我怎样才能得到这样的物体?有些工厂还是其他什么?

2 个答案:

答案 0 :(得分:1)

  1. 你正在混淆工厂和实体。这是不必要的 - 让GetData成为BTAC上的实例方法真的没有意义。
  2. Activator.CreateInstance返回object - 您需要明确地将其转换为您想要的类型。
  3. 您的两种类型都没有实现ILabelData<object>
  4. 问题是,按照原样,完全没有ILabelData泛型!如果您打算使用object,请从ILabelData中删除通用参数,然后执行以下操作:

    var o = (ILabelData)Activator.CreateInstance(type, new object[] { myID });
    
    var data = o.GetData(myID);
    

    让接口(和GetData方法)通用只有在你实际使用时才有意义

    如果通常直接使用它,并且在一些特殊情况下你只需要它(为什么?),你也可以使界面协变:

    public interface ILabelData<out T>
    {
      T GetData(object id);
    }
    

    这样您就可以在ILabelData<BTAC>中实施BTAC,为您提供“用户友好”BTAC GetData(object)方法,同时仍允许您对ILabelData<object>进行显式转换。即使这样,我也会避免这种做法。闻起来。

答案 1 :(得分:0)

此处的工作代码。

var instances = (from t in System.Reflection.Assembly.GetCallingAssembly().GetTypes()
                        where t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ILabelData<>))
                                 && t.GetConstructor(Type.EmptyTypes) != null
                        select Activator.CreateInstance(t)).ToList();

        foreach (dynamic item in instances)
        {
            var res = item.GetData(1);
        }