如何创建返回实现接口的类的类型的方法的通用接口?

时间:2012-07-25 22:18:51

标签: c# generics types interface

我正在寻找一种方法来定义下面的“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

我还没有真正专注于这一部分,只是对我的主要问题的理论构建更加好奇。

2 个答案:

答案 0 :(得分:3)

您的问题有两种解释;一个是微不足道的,一个是不可能的,所以我会前进并覆盖它们。

  1. 您希望返回同时实现System.TypeTInterface的类型的实例。

    这很简单:只需使用where TType : Typewhere TType : TInterface

  2. 您希望返回System.Type的实例,该实例代表继承自TInterface的类型。

    在.NET(和C#)类型系统中无法指定。

    类型系统只能解析类型层次结构本身的信息,但不能强制执行“受限”运行时属性值等“契约”。关于默认构造函数等有一些黑客攻击,但据我所知,甚至不能测试现有方法(例如,与C ++模板不同,不用说Qi等)。

  3. 更新

    请查看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>

这是你想知道的吗?