Skip to content

Commit

Permalink
Merge pull request #73 from alextercete/bug/reference-type-tasks-thro…
Browse files Browse the repository at this point in the history
…wing-exception

Fix error when returning Task of a reference type
  • Loading branch information
kzu committed Dec 16, 2013
2 parents e499bd3 + 4ec4793 commit 69bf046
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
11 changes: 5 additions & 6 deletions Source/EmptyDefaultValueProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private static object GetReferenceTypeDefault(Type valueType)
else if (valueType == typeof(Task))
{
// Task<T> inherits from Task, so just return Task<bool>
return GetCompletedTaskWithResult(false);
return GetCompletedTaskForType(typeof (bool));
}
#endif
else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
Expand All @@ -115,9 +115,7 @@ private static object GetReferenceTypeDefault(Type valueType)
else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Task<>))
{
var genericType = valueType.GetGenericArguments()[0];

return GetCompletedTaskWithResult(
genericType.IsValueType ? GetValueTypeDefault(genericType) : GetReferenceTypeDefault(genericType));
return GetCompletedTaskForType(genericType);
}
#endif

Expand All @@ -136,14 +134,15 @@ private static object GetValueTypeDefault(Type valueType)
}

#if !NET3x && !SILVERLIGHT
private static Task GetCompletedTaskWithResult(object result)
private static Task GetCompletedTaskForType(Type type)
{
var type = result.GetType();
var tcs = Activator.CreateInstance(typeof (TaskCompletionSource<>).MakeGenericType(type));

var setResultMethod = tcs.GetType().GetMethod("SetResult");
var taskProperty = tcs.GetType().GetProperty("Task");

var result = type.IsValueType ? GetValueTypeDefault(type) : GetReferenceTypeDefault(type);

setResultMethod.Invoke(tcs, new[] {result});
return (Task) taskProperty.GetValue(tcs, null);
}
Expand Down
23 changes: 18 additions & 5 deletions UnitTests/EmptyDefaultValueProviderFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,23 +123,35 @@ public void ProvidesDefaultTask()
}

[Fact]
public void ProvidesDefaultGenericTask()
public void ProvidesDefaultGenericTaskOfValueType()
{
var provider = new EmptyDefaultValueProvider();

var value = provider.ProvideDefault(typeof(IFoo).GetProperty("GenericTaskValue").GetGetMethod());
var value = provider.ProvideDefault(typeof(IFoo).GetProperty("GenericTaskOfValueType").GetGetMethod());

Assert.NotNull(value);
Assert.True(((Task)value).IsCompleted);
Assert.Equal(default(int), ((Task<int>)value).Result);
}

[Fact]
public void ProvidesDefaultGenericTaskOfReferenceType()
{
var provider = new EmptyDefaultValueProvider();

var value = provider.ProvideDefault(typeof(IFoo).GetProperty("GenericTaskOfReferenceType").GetGetMethod());

Assert.NotNull(value);
Assert.True(((Task)value).IsCompleted);
Assert.Equal(default(string), ((Task<string>)value).Result);
}

[Fact]
public void ProvidesDefaultTaskOfGenericTask()
{
var provider = new EmptyDefaultValueProvider();

var value = provider.ProvideDefault(typeof(IFoo).GetProperty("TaskOfGenericTaskValue").GetGetMethod());
var value = provider.ProvideDefault(typeof(IFoo).GetProperty("TaskOfGenericTaskOfValueType").GetGetMethod());

Assert.NotNull(value);
Assert.True(((Task)value).IsCompleted);
Expand All @@ -162,8 +174,9 @@ public interface IFoo
IQueryable QueryableObjects { get; }
#if !NET3x && !SILVERLIGHT
Task TaskValue { get; set; }
Task<int> GenericTaskValue { get; set; }
Task<Task<int>> TaskOfGenericTaskValue { get; set; }
Task<int> GenericTaskOfValueType { get; set; }
Task<string> GenericTaskOfReferenceType { get; set; }
Task<Task<int>> TaskOfGenericTaskOfValueType { get; set; }
#endif
}

Expand Down

0 comments on commit 69bf046

Please sign in to comment.