在运行时检测“dynamic”关键字用作类型参数的使用

7
我猜这个问题的简短回答是“不行”,但我对在C# 4.0中检测动态关键字在运行时的能力很感兴趣,特别是作为方法的泛型类型参数。
为了提供一些背景信息,我们在库中共享了一个RestClient类,它接受一个类型参数来指定在反序列化响应时应使用的类型,例如:
public IRestResponse<TResource> Get<TResource>(Uri uri, IDictionary<string, string> headers)
    where TResource : new()
{
    var request = this.GetRequest(uri, headers);
    return request.GetResponse<TResource>();
}

很遗憾(由于篇幅原因不再赘述),使用dynamic作为类型参数来返回动态类型并不能正常工作 - 我们不得不向类中添加第二个签名以返回动态响应类型:

public IRestResponse<dynamic> Get(Uri uri, IDictionary<string, string> headers)
{
    var request = this.GetRequest(uri, headers);
    return request.GetResponse();
}

然而,将dynamic作为第一个方法的类型参数使用会导致一个非常奇怪的错误,掩盖了实际问题,使得整个调试过程变得头疼。为了帮助其他使用API的程序员,我想尝试检测第一个方法中是否使用了dynamic,以便在编译时根本无法编译或在使用时抛出异常,提示“如果您需要动态响应类型,请使用另一个方法”。基本上可以采取以下两种方式之一:
public IRestResponse<TResource> Get<TResource>(Uri uri, IDictionary<string, string> headers)
    where TResource is not dynamic

或者

public IRestResponse<TResource> Get<TResource>(Uri uri, IDictionary<string, string> headers)
    where TResource : new()
{
    if (typeof(TResource).isDynamic()) 
    {
           throw new Exception();
    }

    var request = this.GetRequest(uri, headers);

    return request.GetResponse<TResource>();
}

这两种情况有可能吗?我们正在使用VS2010和.Net 4.0,但是如果可以使用更高版本的语言特性,我会对.Net 4.5的解决方案感兴趣。


当用户指定为 dynamic 时,运行时的 TResource 只是一个简单的 object。用户是否会尝试使用 Get<object>?这是否需要与 Get<dynamic> 不同处理? - Tim S.
我已经编辑了你的标题。请参阅“问题的标题应该包含“标签”吗?”,共识是“不应该”。 - John Saunders
@TimS。是的,使用Get<object>可能是可以的 - 如果不必要,我不想禁止它... - Henry Wilson
哦,如果你有 Resharper(或其他代码分析工具,比如 StyleCop?),你可能能够编写一个自定义规则,使 dynamic 在这里是不被允许的。除此之外,我不知道。 - Tim S.
我们在开发团队中同时使用ReSharper和Stylecop,但我不想采用这种方式,因为a)它可能涉及非常复杂的规则,b)依赖于我们的工具集保持静态,而这可能不是事实。我怀疑我将禁止使用Get<object>,但我对更大的问题感兴趣,即是否有任何方法可以明确检测到使用dynamic而不是object。 - Henry Wilson
1个回答

3

当有人执行 Get<dynamic> 时,在运行时 TResource 就会是 object。只要 Get<object> 不是你的用户实际想要做的事情,你可以检查 TResource 是否为 object 来捕获这两种意外情况(objectdynamic)。

public IRestResponse<TResource> Get<TResource>(Uri uri, IDictionary<string, string> headers)
    where TResource : new()
{
    if (typeof(TResource) == typeof(object)) 
    {
        throw new Exception("Use the dynamic one");
    }

    var request = this.GetRequest(uri, headers);

    return request.GetResponse<TResource>();
}

如上面的评论所述,如果可能的话,我想避免禁止使用 Get<object>... - Henry Wilson
在运行时,TResourceobject - 不,那是 TResource 的静态类型 - 运行时类型将是 ExpandoObject - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接