实例化一个实现通用接口的 class

Instantiate a class which implements a generic interface

我有一个用于指定 GetData 方法的接口,其中 returns class 的一个实例通过其 ID

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

并且还有许多不同的 classes 那些实现接口并当然有成员的人:

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/... class 并调用它们的 GetData 方法。 (它的目的是因为在我拥有所需的实例之后我想获取它的成员和属性。获取成员和属性不是我的问题的一部分。)

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

问题是编译器错误 无法将类型 'object' 隐式转换为 'ILabelData< object >'

在实例化正确的 class 之后,我当然也需要成员和属性,所以返回 ILabelData 类型的对象是不够的。

我怎样才能得到这样的对象?一些工厂还是什么?

工作代码在这里。

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);
        }
  1. 您混淆了工厂和实体。这是不必要的——让 GetData 成为 BTAC 上的实例方法确实没有意义。
  2. Activator.CreateInstance returns object - 您需要明确地将其转换为您想要的类型。
  3. 您的类型都没有实现 ILabelData<object>

问题是,使用原样的代码,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);
}

这将允许您在 BTAC 中实现 ILabelData<BTAC>,为您提供 "user friendly" BTAC GetData(object) 方法,同时仍然允许您对 ILabelData<object>。即使那样,我也会避免这种方法。真香。