我正在寻找一种方法来定义下面的“MethodA”,这样它就会返回一个类定义(System.Type),其中所述类型的实例实现了“InterfaceB”
interface IMyInterface
{
TType MethodA<TType, TInterface>()
: where TType : System.Type
: where [instanceOf(TType)] : TInterface
}
(注意:instanceOf不是真的,当然......)
我怀疑在编译时不可能得到这种验证。我希望有人会证明我错了。
提前感谢任何指导。
编辑:我已经更新了这个,希望更具体地说返回的是一个System.Type,后面的代码可以执行:
var classType = myInterface.MethodA<(something, ISomeInterface)>();
ISomeInterface = new classType(); //--Assuming default constructor
我还没有真正专注于这一部分,只是对我的主要问题的理论构建更加好奇。
答案 0 :(得分:3)
您的问题有两种解释;一个是微不足道的,一个是不可能的,所以我会前进并覆盖它们。
您希望返回同时实现System.Type
和TInterface
的类型的实例。
这很简单:只需使用where TType : Type
和where TType : TInterface
。
您希望返回System.Type
的实例,该实例代表继承自TInterface
的类型。
在.NET(和C#)类型系统中无法指定。
类型系统只能解析类型层次结构本身的信息,但不能强制执行“受限”运行时属性值等“契约”。关于默认构造函数等有一些黑客攻击,但据我所知,甚至不能测试现有方法(例如,与C ++模板不同,不用说Qi等)。
更新
请查看Michael Graczyk的评论。
另外:我刚刚发现.NET有代码合同检查程序(静态和运行时):Microsoft DevLabs Code-Contracts for .NET。我从来没有使用它们,甚至没有使用它们,但这看起来很有趣!
然而,即使没有看,我也很确定超载分辨率等不能使用这些信息。
答案 1 :(得分:0)
在这种情况下:
// We have an interface...
interface InterfaceB {}
// And this class implements the interface.
class ImplementsB : InterfaceB {}
// But this class does not.
class DoesNotImplementB {}
您可以将MethodA
定义为:
static Type MethodA<TClass, TInterface>()
where TClass : TInterface
{
return typeof(TClass);
}
然后以下内容将起作用:
Type t = MethodA<ImplementsB, InterfaceB>();
但这会产生编译时错误:
Type t = MethodA<DoesNotImplementB, InterfaceB>();
类型'DoesNotImplementB'不能在泛型类型或方法'MethodA&lt; TClass,TInterface&gt;()'中用作类型参数'TClass'。没有从'DoesNotImplementB'到'InterfaceB'的隐式引用转换。
因此,通过这种方式,您确定MethodA
的结果是实现Type
的类的TInterface
。鉴于Type
对象,您可以稍后将其更改为:
public object Instantiate(Type type)
{
// Call the default constructor.
// You can change this to call any constructor you want.
var constructor = type.GetConstructor(Type.EmptyTypes);
var instance = constructor.Invoke(new object[0]);
return instance;
}
如果您知道自己的Type
与某个界面TInterface
兼容,那么您可以避免使用其他方法进行投射:
public TInterface Instantiate<TInterface>(Type type)
{
return (TInterface)Instantiate(type);
}
但是,如果type
是某个Type
TInterface
未实现InvalidCastException
,那么您将在运行时获得Type
。没有办法将InvalidCastException
约束为在编译时实现特定接口的类型。但是,在运行时,您可以检查它以避免public TInterface Instantiate<TInterface>(Type type)
{
if (!typeof(TInterface).IsAssignableFrom(type))
throw new Exception("Wrong type!");
return (TInterface)Instantiate(type);
}
异常:
typeof(TType)
请注意,Type
是一个导致typeof()
对象的表达式,因此您看到Type
的任何位置都可以将其替换为任何{{1}}变量,反之亦然。< / p>
这是你想知道的吗?