Detecting use of "dynamic" keyword as a type parameter at runtime
Asked Answered
T

1

7

I suspect the short answer to this question is "no" but I'm interested in the ability to detect the use of the dynamic keyword at runtime in C# 4.0, specifically as a generic type parameter for a method.

To give some background, we have a RestClient class in a library shared among a number of our projects which takes a type parameter to specify a type that should be used when de-serializing the response, e.g.:

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

Unfortunately (due to reasons I won't get into here for the sake of brevity) using dynamic as the type parameter in order to return a dynamic type doesn't work properly - we've had to add a second signature to the class to return a dynamic response type:

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

However, using dynamic as the type parameter to the first method causes a very strange error that masks the actual problem and makes debugging the whole thing a headache. In order to help out the other programmers using the API, I'd like to try and detect the use of dynamic in the first method so that either it won't compile at all or when used an exception is thrown saying something along the lines of "use this other method if you want a dynamic response type".

Basically either:

public IRestResponse<TResource> Get<TResource>(Uri uri, IDictionary<string, string> headers)
    where TResource is not dynamic

or

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>();
}

Are either of these things possible? We're using VS2010 and .Net 4.0 but I'd be interested in a .Net 4.5 solution for future reference if it's possible using newer language features.

Turpin answered 4/10, 2013 at 11:37 Comment(5)
TResource at runtime is simply object when the user specified dynamic. Would users ever try to Get<object>? Does that need to be handled differently from Get<dynamic>?Ilbert
I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not".Phidippides
@TimS. yeah use of Get<object> is potentially OK - I don't wanna outlaw that if I don't have to...Turpin
Hm..if you have Resharper (or some other code analysis tool, maybe StyleCop?), you might be able to write a custom rule that makes dynamic a no-no here. Other than that, I don't know.Ilbert
We use both ReSharper and Stylecop within the development team but that's not a route I particularly wanna employ since it'll a) likely involve a really convoluted rule and b) relies on our toolset remaining static, which it may not. I suspect I'll resort to banning Get<object> but I'm interested in the larger question as to whether there is any way to explicitly detect the use of dynamic rather than objectTurpin
I
3

When someone does Get<dynamic>, at runtime TResource is object. As long as Get<object> isn't something your users would actually want to do, you can just check if TResource is object to catch both unexpected cases (object and dynamic).

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>();
}
Ilbert answered 4/10, 2013 at 11:50 Comment(2)
As noted in comments above, I'd like to avoid outlawing Get<object> if possible...Turpin
"at runtime TResource is object" - no, that's the static type of TResource - the runtime type will be ExpandoObject.Fluke

© 2022 - 2024 — McMap. All rights reserved.