e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
354 lines
9.2 KiB
C#
354 lines
9.2 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace System.Activities
|
|
{
|
|
using System;
|
|
using System.Activities.Runtime;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Runtime.Serialization;
|
|
using System.Runtime;
|
|
using System.Collections.Specialized;
|
|
|
|
[DataContract]
|
|
[DebuggerDisplay("{Value}")]
|
|
public abstract class Location
|
|
{
|
|
TemporaryResolutionData temporaryResolutionData;
|
|
|
|
protected Location()
|
|
{
|
|
}
|
|
|
|
public abstract Type LocationType
|
|
{
|
|
get;
|
|
}
|
|
|
|
public object Value
|
|
{
|
|
get
|
|
{
|
|
return this.ValueCore;
|
|
}
|
|
set
|
|
{
|
|
this.ValueCore = value;
|
|
}
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "temporaryResolutionData")]
|
|
internal TemporaryResolutionData SerializedTemporaryResolutionData
|
|
{
|
|
get { return this.temporaryResolutionData; }
|
|
set { this.temporaryResolutionData = value; }
|
|
}
|
|
|
|
internal virtual bool CanBeMapped
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// When we are resolving an expression that resolves to a
|
|
// reference to a location we need some way of notifying the
|
|
// LocationEnvironment that it should extract the inner location
|
|
// and throw away the outer one. OutArgument and InOutArgument
|
|
// create these TemporaryResolutionLocations if their expression
|
|
// resolution goes async and LocationEnvironment gets rid of them
|
|
// in CollapseTemporaryResolutionLocations().
|
|
internal LocationEnvironment TemporaryResolutionEnvironment
|
|
{
|
|
get
|
|
{
|
|
return this.temporaryResolutionData.TemporaryResolutionEnvironment;
|
|
}
|
|
}
|
|
|
|
internal bool BufferGetsOnCollapse
|
|
{
|
|
get
|
|
{
|
|
return this.temporaryResolutionData.BufferGetsOnCollapse;
|
|
}
|
|
}
|
|
|
|
protected abstract object ValueCore
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
internal void SetTemporaryResolutionData(LocationEnvironment resolutionEnvironment, bool bufferGetsOnCollapse)
|
|
{
|
|
this.temporaryResolutionData = new TemporaryResolutionData
|
|
{
|
|
TemporaryResolutionEnvironment = resolutionEnvironment,
|
|
BufferGetsOnCollapse = bufferGetsOnCollapse
|
|
};
|
|
}
|
|
|
|
internal virtual Location CreateReference(bool bufferGets)
|
|
{
|
|
if (this.CanBeMapped || bufferGets)
|
|
{
|
|
return new ReferenceLocation(this, bufferGets);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
internal virtual object CreateDefaultValue()
|
|
{
|
|
Fx.Assert("We should only call this on Location<T>");
|
|
return null;
|
|
}
|
|
|
|
[DataContract]
|
|
internal struct TemporaryResolutionData
|
|
{
|
|
[DataMember(EmitDefaultValue = false)]
|
|
public LocationEnvironment TemporaryResolutionEnvironment
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false)]
|
|
public bool BufferGetsOnCollapse
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
}
|
|
|
|
[DataContract]
|
|
internal class ReferenceLocation : Location
|
|
{
|
|
Location innerLocation;
|
|
bool bufferGets;
|
|
object bufferedValue;
|
|
|
|
public ReferenceLocation(Location innerLocation, bool bufferGets)
|
|
{
|
|
this.innerLocation = innerLocation;
|
|
this.bufferGets = bufferGets;
|
|
}
|
|
|
|
public override Type LocationType
|
|
{
|
|
get
|
|
{
|
|
return this.innerLocation.LocationType;
|
|
}
|
|
}
|
|
|
|
protected override object ValueCore
|
|
{
|
|
get
|
|
{
|
|
if (this.bufferGets)
|
|
{
|
|
return this.bufferedValue;
|
|
}
|
|
else
|
|
{
|
|
return this.innerLocation.Value;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
this.innerLocation.Value = value;
|
|
this.bufferedValue = value;
|
|
}
|
|
}
|
|
|
|
[DataMember(Name = "innerLocation")]
|
|
internal Location SerializedInnerLocation
|
|
{
|
|
get { return this.innerLocation; }
|
|
set { this.innerLocation = value; }
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "bufferGets")]
|
|
internal bool SerializedBufferGets
|
|
{
|
|
get { return this.bufferGets; }
|
|
set { this.bufferGets = value; }
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "bufferedValue")]
|
|
internal object SerializedBufferedValue
|
|
{
|
|
get { return this.bufferedValue; }
|
|
set { this.bufferedValue = value; }
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if (bufferGets)
|
|
{
|
|
return base.ToString();
|
|
}
|
|
else
|
|
{
|
|
return this.innerLocation.ToString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[DataContract]
|
|
public class Location<T> : Location
|
|
{
|
|
T value;
|
|
|
|
public Location()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
public override Type LocationType
|
|
{
|
|
get
|
|
{
|
|
return typeof(T);
|
|
}
|
|
}
|
|
|
|
public virtual new T Value
|
|
{
|
|
get
|
|
{
|
|
return this.value;
|
|
}
|
|
set
|
|
{
|
|
this.value = value;
|
|
}
|
|
}
|
|
|
|
internal T TypedValue
|
|
{
|
|
get
|
|
{
|
|
return this.Value;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.Value = value;
|
|
}
|
|
}
|
|
|
|
protected override sealed object ValueCore
|
|
{
|
|
get
|
|
{
|
|
return this.Value;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.Value = TypeHelper.Convert<T>(value);
|
|
}
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "value")]
|
|
internal T SerializedValue
|
|
{
|
|
get { return this.value; }
|
|
set { this.value = value; }
|
|
}
|
|
|
|
internal override Location CreateReference(bool bufferGets)
|
|
{
|
|
if (this.CanBeMapped || bufferGets)
|
|
{
|
|
return new ReferenceLocation(this, bufferGets);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
internal override object CreateDefaultValue()
|
|
{
|
|
Fx.Assert(typeof(T).GetGenericTypeDefinition() == typeof(Location<>), "We should only be calling this with location subclasses.");
|
|
|
|
return Activator.CreateInstance<T>();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return this.value != null ? this.value.ToString() : "<null>";
|
|
}
|
|
|
|
[DataContract]
|
|
internal new class ReferenceLocation : Location<T>
|
|
{
|
|
Location<T> innerLocation;
|
|
bool bufferGets;
|
|
|
|
public ReferenceLocation(Location<T> innerLocation, bool bufferGets)
|
|
{
|
|
this.innerLocation = innerLocation;
|
|
this.bufferGets = bufferGets;
|
|
}
|
|
|
|
public override T Value
|
|
{
|
|
get
|
|
{
|
|
if (this.bufferGets)
|
|
{
|
|
return this.value;
|
|
}
|
|
else
|
|
{
|
|
return this.innerLocation.Value;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
this.innerLocation.Value = value;
|
|
|
|
if (this.bufferGets)
|
|
{
|
|
this.value = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
[DataMember(Name = "innerLocation")]
|
|
internal Location<T> SerializedInnerLocation
|
|
{
|
|
get { return this.innerLocation; }
|
|
set { this.innerLocation = value; }
|
|
}
|
|
|
|
[DataMember(EmitDefaultValue = false, Name = "bufferGets")]
|
|
internal bool SerializedBufferGets
|
|
{
|
|
get { return this.bufferGets; }
|
|
set { this.bufferGets = value; }
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if (this.bufferGets)
|
|
{
|
|
return base.ToString();
|
|
}
|
|
else
|
|
{
|
|
return this.innerLocation.ToString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|