diff --git a/package/CHANGELOG.md b/package/CHANGELOG.md
index f64af08fd..693c6f5d1 100755
--- a/package/CHANGELOG.md
+++ b/package/CHANGELOG.md
@@ -4,5 +4,5 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## [0.3.8-preview] - 2018-10-26
+## [0.4.0-preview] - 2018-11-12
Latest preview release.
diff --git a/package/Documentation~/index.md b/package/Documentation~/index.md
index 872dba4e9..40e68382b 100755
--- a/package/Documentation~/index.md
+++ b/package/Documentation~/index.md
@@ -1,11 +1,11 @@
# Unity Properties
-Unity Properties are a set of interface and runtime implementation that offer a very fexible and efficient framework for data container description and visitation services.
+Unity Properties are a set of interfaces and runtime implementation that offer a very fexible and efficient framework for data container description and visitation services.
# About the Property API
Use the Property API package to include the `Unity.Properties` namespace in your project. This namespace contains interfaces and classes you can use to:
- * describe .Net types as property containers
+ * describe or wrap .Net types as property containers
* resolve properties in nested property containers
* implement visitors to traverse property containers and perform tasks (e.g. schema generation, serialization, UI generation, etc.)
@@ -16,28 +16,341 @@ The Property API differs from the available .Net RTTI in multiple aspects:
# Installing the Property API
-To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html).
+To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html).
-# Using the Property API
+# Code Generation
-**TODO**
+## Property Schema
-# Technical details
-## Requirements
+You can use the `Unity.Properties.Codegen.Schema` API to build the representation of a property container type. This `Schema` object implements the `IPropertyContaner` interface, and can be serialized using the Property API.
-This version of the Property API is compatible with the following versions of the Unity Editor:
+By serializing it to JSON and saving it to a file ending with the `.properties` extension, you can use the `Unity.Properties.Codegen.SchemaImporter` to inspect the schema and generate C# code in the Unity Editor on demand.
-* 2018.1 and later (recommended)
+Here's a simple example:
-To use this package, you must use the following project settings:
-* .Net 4.x: To configure, open *Edit > Project Settings > Player*, and set the *Scripting Runtime Version* to *Experimental (.Net 4.x Equivalent*. Additionally, make sure *Api Compatibility Level* is set to *.Net 4.x*.
+```csharp
+using Unity.Properties.Codegen;
+using Unity.Properties.Codegen.CSharp;
+using Unity.Properties.Serialization;
+using UnityEditor;
-## Known limitations
+namespace Sample
+{
+ internal static class SchemaCodeGeneration
+ {
+ [MenuItem("Properties/Generate")]
+ static void Generate()
+ {
+ var schema = new Schema();
+ var myClass = new TypeNode()
+ {
+ Name = "MyClass",
+ Namespace = "Sample"
+ };
+ myClass.Properties.Add(new PropertyNode()
+ {
+ Name = "IntValue",
+ PropertyType = PropertyType.Value,
+ ValueType = "int",
+ Documentation = "This is an int value"
+ });
+ schema.Types.Add(myClass);
-**TODO**
+ // Optional:
+ // save the schema using the `.properties` extension
+ // useful if you don't want to programmatically generate the schema object
+ File.WriteAllText("Assets/MyClass.properties", JsonSerializer.Serialize(schema));
-## Document revision history
+ // generate the C# code
+ // you can do the same thing by pressing the "Generate" button on the properties asset inspector
+ var builder = new CSharpSchemaBuilder();
+ builder.Build("Assets/MyClass.Properties.cs", schema);
+
+ AssetDatabase.Refresh();
+ }
+ }
+}
+```
+
+The serialized shema object looks like this:
+```json
+{
+ "Types": [{
+ "Namespace": "Sample",
+ "Name": "MyClass",
+ "Properties": [{
+ "Name": "IntValue",
+ "ValueType": "int",
+ "PropertyType": "Value",
+ "Documentation": "This is an int value"
+ }]
+ }]
+}
+```
+
+And the generated C# code looks like this. By default, the generated classes or structs are `public` and `partial`. This allows you to define your custom logic in a separate C# file.
+
+There are many options to control the C# code generation output. See the `Unity.Properties.Codegen.Schema` API documentation for details.
+
+```csharp
+#if (NET_4_6 || NET_STANDARD_2_0)
+using System;
+using System.Collections.Generic;
+using Unity.Properties;
+
+namespace Sample
+{
+ public partial class MyClass : IPropertyContainer
+ {
+ ///
+ /// property.
+ ///
+ public static ValueClassProperty IntValueProperty { get; private set; }
+
+ private static ClassPropertyBag s_PropertyBag { get; set; }
+
+ ///
+ public IPropertyBag PropertyBag => s_PropertyBag;
+ ///
+ public IVersionStorage VersionStorage => null;
+
+ private static void InitializeProperties()
+ {
+ IntValueProperty = new ValueClassProperty(
+ "IntValue"
+ ,c => c.m_IntValue
+ ,(c, v) => c.m_IntValue = v
+ );
+ }
+
+ static partial void InitializeCustomProperties();
+
+ private static void InitializePropertyBag()
+ {
+ s_PropertyBag = new ClassPropertyBag(
+ IntValueProperty
+ );
+ }
+
+ static MyClass()
+ {
+ InitializeProperties();
+ InitializeCustomProperties();
+ InitializePropertyBag();
+ }
+
+ private int m_IntValue;
+
+ ///
+ /// This is an int value
+ ///
+ public int IntValue
+ {
+ get { return IntValueProperty.GetValue(this); }
+ set { IntValueProperty.SetValue(this, value); }
+ }
+ }
+}
+#endif // (NET_4_6 || NET_STANDARD_2_0)
+```
+
+# Creating Property Containers
+
+To work with Properties, you need to instrument your .Net types with the `Unity.Properties.IPropertyContainer` interface.
+
+This interface declares a `Unity.Properties.IPropertyBag`, essentially exposing a list of properties for this particular type to consumers of the API.
+
+This manual instrumentation can be tedious (and error-prone!). Refer to the [Code Generation](#CodeGeneration) section for alternative code instrumentation methods.
+
+## Class Containers
+
+Property types available to `class` containers all have the `ClassProperty` suffix.
+
+```csharp
+// Class container example instrumented with static properties
+class MyClass : IPropertyContainer
+{
+ // Property declarations
+ // properties themselves can have any access modifier (public, internal, protected, private).
+ // They'll be available as long as they're added to the type's property bag (see below).
+
+ // Value property types
+ public static ValueClassProperty SimpleValueProperty { get; private set; }
+ public static ClassValueClassProperty ClassContainerProperty { get; private set; }
+ public static StructValueClassProperty StructContainerProperty { get; private set; }
+
+ // List property types
+ public static ValueListClassProperty SimpleValueListProperty { get; private set; }
+ public static ClassListClassProperty ListOfClassContainersProperty { get; private set; }
+ public static StructListClassProperty ListOfStructContainersProperty { get; private set; }
+
+ // Backing Storage
+ // here we're using .Net fields hosted on the instance itself, but the data can come from anywhere
+ // For example, the data could come from a native (unmanaged) data store, or could live on another .Net object.
+
+ private int m_SimpleValue;
+ private MyOtherClass m_ClassContainer;
+ private MyOtherStruct m_StructContainer;
+ private readonly List m_SimpleValueList = new List();
+ private readonly List m_ListOfClassContainers = new List();
+ private readonly List m_ListOfStructContainers = new List();
+
+ // Setup
+
+ private static void InitializeProperties()
+ {
+ // All property types use delegates to access backing storage while preserving encapsulation
+ // The delegates here are anonymous and static, and will not allocate.
+
+ // You can put anything in a Value property, as long as the algorithms support the value type.
+ // Algorithms built on top of Properties are encouraged to support all .Net primitive types, including
+ // enum types.
+
+ SimpleValueProperty = new ValueClassProperty(
+ "SimpleValue"
+ , c => c.m_SimpleValue // read instance data (get)
+ , (c, v) => c.m_SimpleValue = v // write instance data (set)
+ );
+
+ // Use ClassContainer or StructContainer properties to recurse into complex types while visiting
+ // Note that ClassContainerProperty does not handle cyclic references automatically.
+
+ ClassContainerProperty = new ClassValueClassProperty(
+ "ClassContainer"
+ , c => c.m_ClassContainer
+ , (c, v) => c.m_ClassContainer = v
+ );
+
+ StructContainerProperty = new StructValueClassProperty(
+ "StructContainer"
+ , c => c.m_StructContainer
+ , (c, v) => c.m_StructContainer = v
+ );
+
+ // List properties can be used to represent ordered collections of items
+ // Lists must be backed by a type that implements the `System.Collections.Generic.IList` interface.
+
+ SimpleValueListProperty = new ValueListClassProperty(
+ "SimpleValueList"
+ , c => c.m_SimpleValueList // get list
+ );
+
+ // The 2nd delegate is optional, and defaults to use `default(TValue)` when adding a new item.
+ // You usually want to provide an item creation delegate when working with `class` value, otherwise new
+ // items will default to `null`.
+
+ ListOfClassContainersProperty = new ClassListClassProperty(
+ "ListOfClassContainers"
+ , c => c.m_ListOfClassContainers
+ , c => new MyOtherClass() // create list item
+ );
+
+ ListOfStructContainersProperty = new StructListClassProperty(
+ "ListOfStructContainers"
+ , c => c.m_ListOfStructContainers
+ );
+ }
+
+ private static ClassPropertyBag s_PropertyBag { get; set; }
+
+ private static void InitializePropertyBag()
+ {
+ // A property bag is simply an ordered list of properties
+
+ s_PropertyBag = new ClassPropertyBag(
+ SimpleValueProperty
+ , ClassContainerProperty
+ , StructContainerProperty
+ , SimpleValueListProperty
+ , ListOfClassContainersProperty
+ , ListOfStructContainersProperty
+ );
+ }
+
+ static MyClass()
+ {
+ InitializeProperties();
+ InitializePropertyBag();
+ }
+
+ // IPropertyContainer interface implementation
+
+ public IPropertyBag PropertyBag => s_PropertyBag;
+ public IVersionStorage VersionStorage => null;
+}
+
+class MyOtherClass : IPropertyContainer { }
+struct MyOtherStruct : IStructPropertyContainer { }
+```
+
+## Struct Containers
+
+Property types available to `struct` containers all end with the `StructProperty` suffix.
+
+Struct containers require a bit more code to instrument, since they must be passed by reference in order to support data mutation during visits while preserving performance (no boxing, less copies).
+
+`struct` containers should therefore use the extended `IStructPropertyContainer` interface.
+
+```csharp
+public struct MyStruct : IStructPropertyContainer
+{
+ public static ValueStructProperty NameProperty { get; private set; }
+
+ private static StructPropertyBag s_PropertyBag { get; set; }
+
+ public IPropertyBag PropertyBag => s_PropertyBag;
+ public IVersionStorage VersionStorage => null;
+
+ private static void InitializeProperties()
+ {
+ // note that the delegates now get the container by reference
+
+ NameProperty = new ValueStructProperty(
+ "Name"
+ ,(ref MyStruct c) => c.m_Name
+ ,(ref MyStruct c, string v) => c.m_Name = v
+ );
+ }
+
+ private static void InitializePropertyBag()
+ {
+ s_PropertyBag = new StructPropertyBag(
+ NameProperty
+ );
+ }
+
+ static MyStruct()
+ {
+ InitializeProperties();
+ InitializePropertyBag();
+ }
+
+ private string m_Name;
+
+ public string Name
+ {
+ get { return NameProperty.GetValue(ref this); }
+ set { NameProperty.SetValue(ref this, value); }
+ }
+
+ // IStructPropertyContainer implementation
+
+ public void MakeRef(ByRef byRef, TContext context)
+ {
+ byRef(ref this, context);
+ }
+
+ public TReturn MakeRef(ByRef byRef, TContext context)
+ {
+ return byRef(ref this, context);
+ }
+}
+```
+
+# Document revision history
|Date|Reason|
|---|---|
-|Feb 14, 2018|Document created. Matches package version 0.1.0|
\ No newline at end of file
+|Nov 12, 2018|Removed Roslyn-base code generation path.|
+|Oct 27, 2018|Added documentation around instrumentation and code generation.|
+|Feb 14, 2018|Document created. Matches package version 0.1.0|
diff --git a/package/Unity.Properties.Codegen/Unity.Properties.Codegen.asmdef b/package/Unity.Properties.Codegen/Unity.Properties.Codegen.asmdef
index a33818c12..638d3de2f 100755
--- a/package/Unity.Properties.Codegen/Unity.Properties.Codegen.asmdef
+++ b/package/Unity.Properties.Codegen/Unity.Properties.Codegen.asmdef
@@ -1,6 +1,16 @@
{
"name": "Unity.Properties.Codegen",
- "references": ["Unity.Properties", "Unity.Properties.Codegen.Base", "Unity.Properties.Codegen.Analyzers"],
- "includePlatforms": ["Editor"],
- "excludePlatforms": []
-}
+ "references": [
+ "Unity.Properties"
+ ],
+ "optionalUnityReferences": [],
+ "includePlatforms": [
+ "Editor"
+ ],
+ "excludePlatforms": [],
+ "allowUnsafeCode": false,
+ "overrideReferences": false,
+ "precompiledReferences": [],
+ "autoReferenced": true,
+ "defineConstraints": []
+}
\ No newline at end of file
diff --git a/package/Unity.Properties/IProperty.cs b/package/Unity.Properties/IProperty.cs
index 3b01c6956..631986ca0 100755
--- a/package/Unity.Properties/IProperty.cs
+++ b/package/Unity.Properties/IProperty.cs
@@ -5,17 +5,17 @@
namespace Unity.Properties
{
///
- /// Common nongeneric interface required for all property types
+ /// Interface required for all property types.
///
public interface IProperty
{
///
- /// The name of this property
+ /// The name of this property.
///
string Name { get; }
///
- /// Container type that hosts the data for this property
+ /// Container type that hosts the data for this property.
///
Type ContainerType { get; }
}
@@ -24,14 +24,31 @@ public interface IProperty
* CLASS PROPERTIES
*/
+ ///
+ /// Interface required for all properties where is a class.
+ ///
public interface IClassProperty : IProperty
{
+ ///
+ /// Performs a visit on the given container.
+ ///
+ /// Generic container to visit.
+ /// Visitor performing the visit.
void Accept(IPropertyContainer container, IPropertyVisitor visitor);
}
+ ///
+ /// Specialized for a given class container type.
+ ///
+ /// Property container type.
public interface IClassProperty : IClassProperty
where TContainer : class, IPropertyContainer
{
+ ///
+ /// Performs a visit on the given container.
+ ///
+ /// Container to visit.
+ /// Visitor performing the visit.
void Accept(TContainer container, IPropertyVisitor visitor);
}
@@ -39,14 +56,31 @@ public interface IClassProperty : IClassProperty
* STRUCT PROPERTIES
*/
+ ///
+ /// Interface required for all properties where is a struct.
+ ///
public interface IStructProperty : IProperty
{
+ ///
+ /// Performs a visit on the given container.
+ ///
+ /// Generic container reference to visit.
+ /// Visitor performing the visit.
void Accept(ref IPropertyContainer container, IPropertyVisitor visitor);
}
+ ///
+ /// Specialized for a given struct container type.
+ ///
+ /// Property container type.
public interface IStructProperty : IStructProperty
where TContainer : struct, IPropertyContainer
{
+ ///
+ /// Performs a visit on the given container.
+ ///
+ /// Container reference to visit.
+ /// Visitor performing the visit.
void Accept(ref TContainer container, IPropertyVisitor visitor);
}
}
diff --git a/package/Unity.Properties/IPropertyBag.cs b/package/Unity.Properties/IPropertyBag.cs
index 9ca1d6039..eecf73c0b 100755
--- a/package/Unity.Properties/IPropertyBag.cs
+++ b/package/Unity.Properties/IPropertyBag.cs
@@ -4,10 +4,26 @@
namespace Unity.Properties
{
+ ///
+ /// Represents a collection of objects.
+ ///
public interface IPropertyBag
{
+ ///
+ /// Number of properties in the bag.
+ ///
int PropertyCount { get; }
+
+ ///
+ /// Enumeration of all available properties.
+ ///
IEnumerable Properties { get; }
+
+ ///
+ /// Finds a property by in this bag.
+ ///
+ /// Name of the property to look for.
+ /// The instance, or null if not found.
IProperty FindProperty(string name);
}
}
diff --git a/package/Unity.Properties/IPropertyContainer.cs b/package/Unity.Properties/IPropertyContainer.cs
index 88df96733..38964e071 100755
--- a/package/Unity.Properties/IPropertyContainer.cs
+++ b/package/Unity.Properties/IPropertyContainer.cs
@@ -2,27 +2,74 @@
namespace Unity.Properties
{
+ ///
+ /// Required interface for all types supported by algorithms.
+ ///
public interface IPropertyContainer
{
+ ///
+ /// object this container instance uses to keep track of property changes.
+ ///
IVersionStorage VersionStorage { get; }
+
+ ///
+ /// object defining the properties known to this container.
+ ///
IPropertyBag PropertyBag { get; }
}
+ ///
+ /// Intermediate function call allowing callers to get a struct container by reference.
+ ///
+ /// Container object reference.
+ /// Context object.
+ /// Type of the container object, must be a struct.
+ /// Type of the context object.
public delegate void ByRef(ref TContainer container, TContext context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Intermediate function call allowing callers to get a struct container by reference.
+ ///
+ /// Container object reference.
+ /// Context object.
+ /// Type of the container object, must be a struct.
+ /// Type of the context object.
+ /// Type of the delegate's return value.
public delegate TReturn ByRef(ref TContainer container, TContext context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Interface required on all struct types.
+ ///
public interface IStructPropertyContainer : IPropertyContainer
{
}
+ ///
+ /// Specialized interface for a given struct container type.
+ ///
+ /// Container type, must be a struct.
public interface IStructPropertyContainer : IStructPropertyContainer
where TContainer : struct, IPropertyContainer
{
+ ///
+ /// Calls the given method using this container's reference.
+ ///
+ /// Method to call.
+ /// Context object.
+ /// Context object type.
void MakeRef(ByRef method, TContext context);
+
+ ///
+ /// Calls the given method using this container's reference.
+ ///
+ /// Method to call.
+ /// Context object.
+ /// Context object type.
+ /// Return value type of the given method to call.
+ /// Return value of the given method.
TReturn MakeRef(ByRef method, TContext context);
}
}
diff --git a/package/Unity.Properties/IPropertyVisitor.cs b/package/Unity.Properties/IPropertyVisitor.cs
index e6f6ac228..98acb5142 100755
--- a/package/Unity.Properties/IPropertyVisitor.cs
+++ b/package/Unity.Properties/IPropertyVisitor.cs
@@ -4,96 +4,216 @@
namespace Unity.Properties
{
- ///
- /// Generic visitable class
- ///
- public interface IVisitableClass
+ internal interface IVisitableClass
{
void Visit(TContainer container, IPropertyVisitor visitor)
where TContainer : class, IPropertyContainer;
}
- ///
- /// Generic visitable struct class
- ///
- public interface IVisitableStruct
+ internal interface IVisitableStruct
{
void Visit(ref TContainer container, IPropertyVisitor visitor)
where TContainer : struct, IPropertyContainer;
}
- ///
- /// Typed visitable class
- ///
- ///
- public interface IVisitableClass
+ internal interface IVisitableClass
where TContainer : IPropertyContainer
{
void Visit(TContainer container, IPropertyVisitor visitor);
}
- ///
- /// Typed visitable struct
- ///
- ///
- public interface IVisitableStruct
+ internal interface IVisitableStruct
where TContainer : struct, IPropertyContainer
{
void Visit(ref TContainer container, IPropertyVisitor visitor);
}
+ ///
+ /// Represents a property visit context.
+ /// Object created by implementations and passed to the API.
+ ///
+ /// Type of the value being visited.
public struct VisitContext
{
+ ///
+ /// Property being visited.
+ ///
public IProperty Property;
+
+ ///
+ /// Property value.
+ ///
public TValue Value;
+
+ ///
+ /// Property value index within the collection.
+ /// If the is not a collection property, -1 is returned.
+ ///
public int Index;
}
+ ///
+ /// Base interface for all property visitors.
+ ///
+ ///
+ /// The intent of this interface is to support: non-allocating visits to class and struct ,
+ /// visit exclusion and customization mechanisms, nested property containers, and collection properties.
+ ///
public interface IPropertyVisitor
{
+ ///
+ /// Whether or not to exclude the visit of this container in the given context.
+ ///
+ /// Container about to be visited.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should be excluded, false otherwise.
bool ExcludeVisit(TContainer container, VisitContext context)
where TContainer : class, IPropertyContainer;
+ ///
+ /// Whether or not to exclude the visit of this container in the given context.
+ ///
+ /// Container about to be visited.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should be excluded, false otherwise.
bool ExcludeVisit(ref TContainer container, VisitContext context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Whether or not a custom visit was performed on this container in the given context.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if a custom visit was performed, false otherwise.
bool CustomVisit(TContainer container, VisitContext context)
where TContainer : class, IPropertyContainer;
+ ///
+ /// Whether or not a custom visit was performed on this container in the given context.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if a custom visit was performed, false otherwise.
bool CustomVisit(ref TContainer container, VisitContext context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Performs a generic visit on this container in the given context.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void Visit(TContainer container, VisitContext context)
where TContainer : class, IPropertyContainer;
+ ///
+ /// Performs a generic visit on this container in the given context.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void Visit(ref TContainer container, VisitContext context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Method called when visiting a nested property.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should enter this nested container, false otherwise.
bool BeginContainer(TContainer container, VisitContext context)
where TContainer : class, IPropertyContainer
where TValue : IPropertyContainer;
+ ///
+ /// Method called when visiting a nested property.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should enter this nested container, false otherwise.
bool BeginContainer(ref TContainer container, VisitContext context)
where TContainer : struct, IPropertyContainer
where TValue : IPropertyContainer;
+ ///
+ /// Method always called after ,
+ /// regardless of its return value.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void EndContainer(TContainer container, VisitContext context)
where TContainer : class, IPropertyContainer
where TValue : IPropertyContainer;
+ ///
+ /// Method always called after ,
+ /// regardless of its return value.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void EndContainer(ref TContainer container, VisitContext context)
where TContainer : struct, IPropertyContainer
where TValue : IPropertyContainer;
+ ///
+ /// Method called when visiting a collection property.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should enter this collection, false otherwise.
bool BeginCollection(TContainer container, VisitContext> context)
where TContainer : class, IPropertyContainer;
+ ///
+ /// Method called when visiting a collection property.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
+ /// true if the visit should enter this collection, false otherwise.
bool BeginCollection(ref TContainer container, VisitContext> context)
where TContainer : struct, IPropertyContainer;
+ ///
+ /// Method always called after ,
+ /// regardless of its return value.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void EndCollection(TContainer container, VisitContext> context)
where TContainer : class, IPropertyContainer;
+ ///
+ /// Method always called after ,
+ /// regardless of its return value.
+ ///
+ /// Container to visit.
+ /// Visit context object.
+ /// Container type.
+ /// Property value type.
void EndCollection(ref TContainer container, VisitContext> context)
where TContainer : struct, IPropertyContainer;
}
@@ -103,7 +223,7 @@ void EndCollection(ref TContainer container, VisitContext for usage.
///
/// Property value type to visit.
- public interface ICustomVisit
+ public interface ICustomVisit
{
///
/// Performs the visitor logic on this property value type.
@@ -112,7 +232,7 @@ public interface ICustomVisit
void CustomVisit(TValue value);
}
- ///
+ ///
///
/// ICustomVisit declarations for all .NET primitive types.
///
diff --git a/package/Unity.Properties/Migration/MigrationContainer.cs b/package/Unity.Properties/Migration/MigrationContainer.cs
index 9e770c719..d11036a9c 100755
--- a/package/Unity.Properties/Migration/MigrationContainer.cs
+++ b/package/Unity.Properties/Migration/MigrationContainer.cs
@@ -669,7 +669,7 @@ public override void Accept(MigrationContainer container, IPropertyVisitor visit
if (visitor.BeginContainer(container, context))
{
- value.Visit(visitor);
+ value?.Visit(visitor);
}
visitor.EndContainer(container, context);
}
diff --git a/package/Unity.Properties/PropertyBag.cs b/package/Unity.Properties/PropertyBag.cs
index c66076e2a..40319d592 100755
--- a/package/Unity.Properties/PropertyBag.cs
+++ b/package/Unity.Properties/PropertyBag.cs
@@ -90,8 +90,13 @@ public void Visit(TContainer container, IPropertyVisitor visitor)
}
else
{
- // Valid scenario when IPropertyContainer is used as TContainer
+ // Valid scenario when IPropertyContainer is used as TContainer for a class
(property as IClassProperty)?.Accept(container, visitor);
+
+ // Valid scenario when IPropertyContainer is used as TContainer for a struct
+ // @TODO Fixme
+ IPropertyContainer c = container;
+ (property as IStructProperty)?.Accept(ref c, visitor);
}
}
}
diff --git a/package/Unity.Properties/PropertyPath.cs b/package/Unity.Properties/PropertyPath.cs
index b49306210..4c0ba6871 100755
--- a/package/Unity.Properties/PropertyPath.cs
+++ b/package/Unity.Properties/PropertyPath.cs
@@ -47,6 +47,21 @@ public PropertyPath(PropertyPath path)
m_Parts = new List(path.m_Parts);
}
+ public void Insert(int index, string propertyName, int listIndex = InvalidListIndex)
+ {
+ Assert.IsFalse(string.IsNullOrEmpty(propertyName));
+
+ if (listIndex < 0)
+ {
+ listIndex = InvalidListIndex;
+ }
+ m_Parts.Insert(index, new Part()
+ {
+ propertyName = propertyName,
+ listIndex = listIndex
+ });
+ }
+
public void Push(string propertyName, int listIndex = InvalidListIndex)
{
Assert.IsFalse(string.IsNullOrEmpty(propertyName));
diff --git a/package/Unity.Properties/Value/Impl/ValuePropertyImpl.cs b/package/Unity.Properties/Value/Impl/ValuePropertyImpl.cs
index 4ff0d098f..805950254 100755
--- a/package/Unity.Properties/Value/Impl/ValuePropertyImpl.cs
+++ b/package/Unity.Properties/Value/Impl/ValuePropertyImpl.cs
@@ -82,7 +82,7 @@ public ValueClassProperty(string name, GetValueMethod getValue, SetValueMethod s
public override void Accept(TContainer container, IPropertyVisitor visitor)
{
var context = new VisitContext {Property = this, Value = GetValue(container), Index = -1};
- if (!visitor.ExcludeOrCustomVisit(container, context))
+ if (false == visitor.ExcludeOrCustomVisit(container, context))
{
visitor.Visit(container, context);
}
@@ -91,7 +91,7 @@ public override void Accept(TContainer container, IPropertyVisitor visitor)
///
///
- /// Property of a class thats hosts a nested class (IPropertyContainer) value
+ /// Property of a class that hosts a nested class (IPropertyContainer) value
///
///
///
diff --git a/package/package.json b/package/package.json
index 2235e858b..6e3991a8d 100755
--- a/package/package.json
+++ b/package/package.json
@@ -1,10 +1,10 @@
{
"name": "com.unity.properties",
"displayName":"Property API",
- "version": "0.3.8-preview",
+ "version": "0.4.0-preview",
"unity": "2018.1",
"description": "Interfaces and utilities to describe and visit data containers.",
- "keywords": ["properties", "property", "schema", "api"],
+ "keywords": ["properties", "property"],
"dependencies": {
}
}
diff --git a/versions.txt b/versions.txt
index 1a5c6693e..997f52fd9 100755
--- a/versions.txt
+++ b/versions.txt
@@ -43,3 +43,4 @@
0.3.6-preview
0.3.7-preview
0.3.8-preview
+0.4.0-preview