Why does this method keep returning dynamics despite the return type in the signature?
So the type returned by the activator (not shown here) is just the POCO I created. There is nothing special about this. But even though the return type GetWrapper
or GetWrapper<T>
return object is of type dynamic, so none of the properties of the returned actual class are considered intellisense. Any ideas?
UPDATE: Sorry John:
public static T GetWrapper<T>(object type, dynamic obj)
where T : class, IRedditObject
{
return GetWrapper(type, obj) as T;
}
public static object GetWrapper(object type, dynamic obj)
{
return Activator.CreateInstance(Types[type.ToString()], obj);
}
public class LinkWrapper : IRedditObject
{
private readonly dynamic _link;
public string Kind { get { return "t3"; } }
public dynamic Data { get { return _link.data; } }
public LinkWrapper(dynamic link)
{
_link = link;
}
public string Domain { get { return Data.domain; } }
}
[TestMethod]
public void Test()
{
var proxy = new SubredditProxy();
var dotnet = proxy.GetSubredditAsync("dotnet").Result;
var child1 = dotnet.data.children[0];
// this is being returned as dynamic
var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);
Assert.IsNotNull(obj);
}
source to share
I strongly suspect that either child1
or child1.kind
is of a type dynamic
, which means that the expression is considered a dynamically linked expression in spite of everything else.
Here's a short but complete example to demonstrate what I mean:
using System;
class Test
{
public static T Foo<T>(object x)
{
return default(T);
}
public static void Main(string[] args)
{
object a = new object();
dynamic b = a;
var c = Foo<string>(a);
var d = Foo<string>(b);
Console.WriteLine(c.SomeRandomMember); // Invalid
Console.WriteLine(d.SomeRandomMember); // Valid
}
}
Invalid operator is not valid because type c
is equal string
- but subsequent operator is fine because type d
is equal dynamic
.
Even though there is only one possible method that it can be bound to at runtime - and even if that binding will always work, the basic rule is that almost any expression that includes a value dynamic
is considered a type dynamic
. (There are a few exceptions such as as
and new
.)
To make the return value non-dynamic, just put your values ββin object
:
var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>
((object) child1.kind, (object) child1);
This will now be a statically linked call. Or you can leave it as a dynamically linked call and use an implicit conversion from type expression dynamic
to other types:
LinkWrapper obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);
source to share