Check IAddressable before DeepCopy (#2383)

* Modified CodeGenerator to check if the item being DeepCopied is an IAddressable before DeepCopying, converting to IGrainReference if so.

* Modified Guard on SerializerGenerator when getting References to IAddressable types before DeepCopy to exclude concrete Grain classes

* Modified CodeGenerator to check if the item being DeepCopied is an IAddressable (but not a concrete class) before DeepCopying, converting to IGrainReference if so.

* Add test for nested Grain->GrainReference conversion

* Improve commenting.

* Handle SystemTarget & avoid IGrainObserver
This commit is contained in:
James Carter 2016-11-17 22:52:23 +00:00 коммит произвёл Sergey Bykov
Родитель 93034a4dbf
Коммит 8fc5f39ec6
4 изменённых файлов: 57 добавлений и 1 удалений

Просмотреть файл

@ -705,12 +705,42 @@ namespace Orleans.CodeGenerator
return getValueExpression;
}
// Addressable arguments must be converted to references before passing.
// IGrainObserver instances cannot be directly converted to references, therefore they are not included.
ExpressionSyntax deepCopyValueExpression;
if (typeof(IAddressable).IsAssignableFrom(this.FieldInfo.FieldType)
&& this.FieldInfo.FieldType.GetTypeInfo().IsInterface
&& !typeof(IGrainObserver).IsAssignableFrom(this.FieldInfo.FieldType))
{
var getAsReference = getValueExpression.Member(
(IAddressable grain) => grain.AsReference<IGrain>(),
this.FieldInfo.FieldType);
// If the value is not a GrainReference, convert it to a strongly-typed GrainReference.
// C#: !(value is GrainReference) ? value.AsReference<TInterface>() : value;
deepCopyValueExpression =
SF.ConditionalExpression(
SF.PrefixUnaryExpression(
SyntaxKind.LogicalNotExpression,
SF.ParenthesizedExpression(
SF.BinaryExpression(
SyntaxKind.IsExpression,
getValueExpression,
typeof(GrainReference).GetTypeSyntax()))),
SF.InvocationExpression(getAsReference),
getValueExpression);
}
else
{
deepCopyValueExpression = getValueExpression;
}
// Deep-copy the value.
Expression<Action> deepCopyInner = () => SerializationManager.DeepCopyInner(default(object));
var typeSyntax = this.FieldInfo.FieldType.GetTypeSyntax();
return SF.CastExpression(
typeSyntax,
deepCopyInner.Invoke().AddArgumentListArguments(SF.Argument(getValueExpression)));
deepCopyInner.Invoke().AddArgumentListArguments(SF.Argument(deepCopyValueExpression)));
}
/// <summary>

Просмотреть файл

@ -11,8 +11,15 @@ namespace UnitTests.GrainInterfaces
//[ReadOnly]
Task<int> GetCalculatedValue();
Task SetNext(IChainedGrain next);
Task SetNextNested(ChainGrainHolder next);
//[ReadOnly]
Task Validate(bool nextIsSet);
Task PassThis(IChainedGrain next);
Task PassThisNested(ChainGrainHolder next);
}
public class ChainGrainHolder
{
public IChainedGrain Next { get; set; }
}
}

Просмотреть файл

@ -61,6 +61,11 @@ namespace UnitTests.Grains
return TaskDone.Done;
}
public Task SetNextNested(ChainGrainHolder next)
{
State.Next = next.Next;
return TaskDone.Done;
}
public Task Validate(bool nextIsSet)
{
@ -80,6 +85,11 @@ namespace UnitTests.Grains
return next.SetNext(this);
}
public Task PassThisNested(ChainGrainHolder next)
{
return next.Next.SetNextNested(new ChainGrainHolder { Next = this });
}
#endregion
}
}

Просмотреть файл

@ -48,6 +48,15 @@ namespace UnitTests.General
g1.PassThis(g2).Wait();
}
[Fact, TestCategory("Functional"), TestCategory("GrainReference")]
public void GrainReference_Pass_this_Nested()
{
IChainedGrain g1 = GrainClient.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
IChainedGrain g2 = GrainClient.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
g1.PassThisNested(new ChainGrainHolder { Next = g2 }).Wait();
}
[Fact, TestCategory("Functional"), TestCategory("Serialization"), TestCategory("GrainReference")]
public void GrainReference_DotNet_Serialization()
{