实例化一个实现通用接口的 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);
}
- 您混淆了工厂和实体。这是不必要的——让
GetData
成为 BTAC
上的实例方法确实没有意义。
Activator.CreateInstance
returns object
- 您需要明确地将其转换为您想要的类型。
- 您的类型都没有实现
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>
。即使那样,我也会避免这种方法。真香。
我有一个用于指定 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);
}
- 您混淆了工厂和实体。这是不必要的——让
GetData
成为BTAC
上的实例方法确实没有意义。 Activator.CreateInstance
returnsobject
- 您需要明确地将其转换为您想要的类型。- 您的类型都没有实现
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>
。即使那样,我也会避免这种方法。真香。