public static ReverseOptions AddFilterOption <TDefinition>(
            this ReverseOptions options, Expression <Func <TDefinition, bool> > filterExpression)
            where TDefinition : DefinitionBase
        {
            var definitionClassName = typeof(TDefinition).FullName;

            var newOption = new ReverseFilterOption();

            newOption.DefinitionClassFullName = definitionClassName;

            var parsedFilter = new ReverseOptionService().ParseOptionFilter(filterExpression);

            newOption.Filter = parsedFilter;

            var existingOption = options.Options
                                 .FirstOrDefault(o =>
                                                 o.DefinitionClassFullName == definitionClassName &&
                                                 o.Equals(newOption) &&
                                                 o is ReverseFilterOption) as ReverseFilterOption;

            if (existingOption == null)
            {
                options.Options.Add(newOption);
            }

            return(options);
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<ListViewReverseHost>();

            var typedHost = parentHost.WithAssertAndCast<ListReverseHost>("reverseHost", value => value.RequireNotNull());

            var site = typedHost.HostSite;
            var web = typedHost.HostWeb;
            var list = typedHost.HostList;

            var context = typedHost.HostClientContext;

            var items = list.Views;

            context.Load(items);
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(items, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<ListViewReverseHost>(parentHost, h =>
                {
                    h.HostListView = i;
                });
            }));

            return result;
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as SecurityRoleReverseHost).HostRole;

            var def = new SecurityRoleDefinition();

            def.Name = item.Name;
            def.Description = item.Description;

            var allPermissionNames = Enum.GetNames(typeof(PermissionKind));

            foreach (var permissionName in allPermissionNames)
            {
                var permissionValue = (PermissionKind)Enum.Parse(typeof(PermissionKind), permissionName, true);

                if (item.BasePermissions.Has(permissionValue))
                {
                    if (permissionValue != PermissionKind.EmptyMask)
                        def.BasePermissions.Add(permissionName);
                }
            }

            return new SecurityRoleModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public static ReverseOptions WithContentTypes(
            this ReverseOptions options, Expression <Func <ContentTypeDefinition, bool> > filterExpression)
        {
            options.AddFilterOption <ContentTypeDefinition>(filterExpression);

            return(options);
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as UserCustomActionReverseHost).HostUserCustomAction;

            var def = new UserCustomActionDefinition();

            def.Title = item.Title;
            def.Name = item.Name;
            def.Description = item.Description;

            def.Group = item.Group;

            def.ScriptSrc = item.ScriptSrc;
            def.ScriptBlock = item.ScriptBlock;

            def.Location = item.Location;
            def.Sequence = item.Sequence;

            def.Url = item.Url;

            def.RegistrationId = item.RegistrationId;
            def.RegistrationType = item.RegistrationType.ToString();

            return new UserCustomActionModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<FieldReverseHost>();

            var siteHost = parentHost as SiteReverseHost;
            var webHost = parentHost as WebReverseHost;

            var site = siteHost.HostSite;
            var context = siteHost.HostClientContext;

            FieldCollection items = null;

            if (webHost != null)
            {
                items = webHost.HostWeb.Fields;
            }
            else
            {
                items = siteHost.HostSite.RootWeb.Fields;
            }

            var typedItems = GetTypedFields(context, items);

            result.AddRange(ApplyReverseFilters(typedItems, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<FieldReverseHost>(parentHost, h =>
                {
                    h.Field = i;
                });
            }));

            return result;
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<PropertyReverseHost>();

            PropertyValues items = null;

            if (parentHost is ListReverseHost)
                items = (parentHost as ListReverseHost).HostList.RootFolder.Properties;
            else if (parentHost is WebReverseHost)
                items = (parentHost as WebReverseHost).HostWeb.AllProperties;
            else if (parentHost is SiteReverseHost)
                items = (parentHost as SiteReverseHost).HostSite.RootWeb.AllProperties;

            var context = (parentHost as CSOMReverseHostBase).HostClientContext;

            context.Load(items);
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(items.FieldValues.Keys, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<PropertyReverseHost>(parentHost, h =>
                {
                    h.HostPropertyName = i;
                    h.HostPropertyValue = items[i];
                });
            }));

            return result;
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldLookup>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<LookupFieldDefinition>("modelHost", m => m.RequireNotNull());

            typedDef.AllowMultipleValues = typedField.AllowMultipleValues;

            if (typedDef.AllowMultipleValues)
                typedDef.FieldType = BuiltInFieldTypes.LookupMulti;
            else
                typedDef.FieldType = BuiltInFieldTypes.Lookup;

            //typedDef.AppendOnly = typedField.AppendOnly;
            //typedDef.RichText = typedField.RichText;

            //typedDef.NumberOfLines = typedField.NumberOfLines;

            //var xml = XDocument.Parse(typedField.SchemaXml);
            //var fieldXml = xml.Root;

            //var unlimValue = ConvertUtils.ToBool(fieldXml.GetAttributeValue("UnlimitedLengthInDocumentLibrary"));
            //typedDef.UnlimitedLengthInDocumentLibrary = unlimValue.HasValue ? unlimValue.Value : false;

            //var richTextMode = ConvertUtils.ToString(fieldXml.GetAttributeValue("RichTextMode"));
            //typedDef.RichTextMode = richTextMode;
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<TaxonomyTermStoreReverseHost>();

            var typedHost = parentHost.WithAssertAndCast<SiteReverseHost>("reverseHost", value => value.RequireNotNull());

            var context = typedHost.HostClientContext;
            var site = typedHost.HostSite;

            var session = TaxonomySession.GetTaxonomySession(context);
            var termStore = session.GetDefaultSiteCollectionTermStore();

            context.Load(site);
            context.Load(termStore);

            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(new[] { site }, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<TaxonomyTermStoreReverseHost>(parentHost, h =>
                {
                    h.HostTermStore = termStore;
                });
            }));

            return result;
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<SandboxSolutionReverseHost>();

            var typedHost = parentHost.WithAssertAndCast<SiteReverseHost>("reverseHost", value => value.RequireNotNull());

            var site = typedHost.HostSite;
            var context = typedHost.HostClientContext;

            var solutionList = site.RootWeb.GetCatalog((int)ListTemplateType.SolutionCatalog);
            var items = solutionList.RootFolder.Files;

            context.Load(items, i => i.Include(f => f.Name,
                                               f => f.ServerRelativeUrl,
                                               f => f.ListItemAllFields));
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(items, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<SandboxSolutionReverseHost>(parentHost, h =>
                {
                    h.HostSandboxSolutionFile = i;
                });
            }));

            return result;
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as SandboxSolutionReverseHost).HostSandboxSolutionFile;
            var context = (reverseHost as SandboxSolutionReverseHost).HostClientContext;

            var def = new SandboxSolutionDefinition();

            def.FileName = item.Name;
            def.SolutionId = ConvertUtils.ToGuid(item.ListItemAllFields["SolutionId"]).Value;

            def.Activate = true;

            using (var stream = File.OpenBinaryDirect(
                context,
                item.ServerRelativeUrl).Stream)
            {
                def.Content = ModuleFileUtils.ReadFully(stream);
            }

            return new SandboxSolutionModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<ListReverseHost>();

            var typedHost = parentHost.WithAssertAndCast<WebReverseHost>("reverseHost", value => value.RequireNotNull());

            var site = typedHost.HostSite;
            var web = typedHost.HostWeb;

            var context = typedHost.HostClientContext;

            var items = web.Lists;

            //context.Load(items, i => i.Include(r => r.RootFolder, r => r.RootFolder.Properties));
            context.Load(items,
                i => i.Include(r => r.RootFolder,
                                    r => r.Title,
                                    r => r.Description,
                                    r => r.Hidden,
                                    r => r.BaseTemplate,
                                    r => r.ContentTypesEnabled)

                );
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(items, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<ListReverseHost>(parentHost, h =>
                {
                    h.HostList = i;
                });
            }));

            return result;
        }
        public static ReverseOptions AddDepthOption <TDefinition>(
            this ReverseOptions options, int depth)
            where TDefinition : DefinitionBase
        {
            if (depth < 0)
            {
                throw new SPMeta2ReverseException("depth should be >= 0");
            }

            var definitionClassName = typeof(TDefinition).FullName;
            var existingOption      = options.Options
                                      .FirstOrDefault(o =>
                                                      o.DefinitionClassFullName == definitionClassName &&
                                                      o is ReverseDepthOption) as ReverseDepthOption;

            if (existingOption == null)
            {
                existingOption = new ReverseDepthOption();
                existingOption.DefinitionClassFullName = definitionClassName;

                options.Options.Add(existingOption);
            }

            existingOption.Depth = depth;

            return(options);
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<TaxonomyFieldReverseHost>();

            var typedHost = parentHost.WithAssertAndCast<SiteReverseHost>("reverseHost", value => value.RequireNotNull());

            var site = typedHost.HostSite;
            var context = typedHost.HostClientContext;

            // TODO        

            //var items = site.RootWeb.SiteGroups;

            //context.Load(items);
            //context.ExecuteQuery();

            //result.AddRange(ApplyReverseFilters(items, options).ToArray().Select(i =>
            //{
            //    return ModelHostBase.Inherit<TaxonomyFieldReverseHost>(parentHost, h =>
            //    {
            //        h.HostGroup = i;
            //    });
            //}));

            return result;
        }
        public static ReverseOptions WithFields(
            this ReverseOptions options, Expression <Func <FieldDefinition, bool> > filterExpression)
        {
            options.AddFilterOption <FieldDefinition>(filterExpression);

            return(options);
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            var result = new List<WelcomePageReverseHost>();

            Folder hostFolder = null;

            if (parentHost is FolderReverseHost)
                hostFolder = (parentHost as FolderReverseHost).HostFolder;
            else if (parentHost is ListReverseHost)
                hostFolder = (parentHost as ListReverseHost).HostList.RootFolder;
            else if (parentHost is WebReverseHost)
                hostFolder = (parentHost as WebReverseHost).HostWeb.RootFolder;

            var context = (parentHost as CSOMReverseHostBase).HostClientContext;

            context.Load(hostFolder);
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(new[] { hostFolder }, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<WelcomePageReverseHost>(parentHost, h =>
                {
                    h.HostFolder = i;
                });
            }));

            return result;
        }
        public static ReverseOptions Include <TDefinition>(
            this ReverseOptions options, Expression <Func <TDefinition, bool> > filterExpression)
            where TDefinition : DefinitionBase
        {
            options.AddFilterOption <TDefinition>(filterExpression);

            return(options);
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldText>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<TextFieldDefinition>("modelHost", m => m.RequireNotNull());

            typedDef.MaxLength = typedField.MaxLength;
        }
        public override ReverseResult Reverse(object modelHost, ReverseOptions options)
        {
            if (!(modelHost is SiteReverseHost)
                && !(modelHost is WebReverseHost))
            {
                throw new Exception("modelHost should be either SiteReverseHost or WebReverseHost");
            }

            return ReverseInternal(modelHost, options);
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var modelNode = new SiteModelNode
            {
                Options = { RequireSelfProcessing = false },
                Value = new SiteDefinition()
            };

            return modelNode;
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldCurrency>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<CurrencyFieldDefinition>("modelHost", m => m.RequireNotNull());

            if (typedField.CurrencyLocaleId > 0)
                typedDef.CurrencyLocaleId = typedField.CurrencyLocaleId;
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldDateTime>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<DateTimeFieldDefinition>("modelHost", m => m.RequireNotNull());

            typedDef.CalendarType = typedField.DateTimeCalendarType.ToString();
            typedDef.DisplayFormat = typedField.DisplayFormat.ToString();
            typedDef.FriendlyDisplayFormat = typedField.FriendlyDisplayFormat.ToString();
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldUrl>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<URLFieldDefinition>("modelHost", m => m.RequireNotNull());

            var xml = XDocument.Parse(typedField.SchemaXml);
            var fieldXml = xml.Root;

            var displayFormat = ConvertUtils.ToString(fieldXml.GetAttributeValue(BuiltInFieldAttributes.Format));
            typedDef.DisplayFormat = displayFormat;
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as WelcomePageReverseHost).HostFolder;

            var def = new WelcomePageDefinition();

            def.Url = item.WelcomePage;

            return new WelcomePageModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var list = (reverseHost as ListViewReverseHost).HostList;
            var item = (reverseHost as ListViewReverseHost).HostListView;

            if (!item.IsPropertyAvailable("Fields"))
            {
                item.Context.Load(item);
                item.Context.Load(item, i => i.ViewFields);

                item.Context.ExecuteQueryWithTrace();
            }

            var def = new ListViewDefinition();

            var xmlDoc = XDocument.Parse(item.ListViewXml);
            var viewXmlNode = xmlDoc.Descendants("View").First();

            var url = viewXmlNode.Attribute("Url")
                                  .Value
                                  .Split('/')
                                  .LastOrDefault();

            def.Title = item.Title;
            def.Url = url;



            def.Hidden = item.Hidden;

            def.IsDefault = item.DefaultView;
            def.IsPaged = item.Paged;

            def.Scope = item.Scope.ToString();

            def.RowLimit = (int)item.RowLimit;
            def.Query = item.ViewQuery;

            def.Type = viewXmlNode.Attribute("Type").Value;

            def.Fields = new System.Collections.ObjectModel.Collection<string>(
                item.ViewFields.ToArray()
                );

            return new ListViewModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as FolderReverseHost).HostFolder;

            var def = new FolderDefinition();

            def.Name = item.Name;

            return new FolderModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override IEnumerable<ReverseHostBase> ReverseHosts(ReverseHostBase parentHost, ReverseOptions options)
        {
            TraceService.Information((int)ReverseLogEventId.ReverseHostsStart, "Processing web reverse host start");

            var result = new List<WebReverseHost>();

            Web web = null;

            if (parentHost is WebReverseHost)
                web = (parentHost as WebReverseHost).HostWeb;
            else if (parentHost is SiteReverseHost)
                web = (parentHost as SiteReverseHost).HostWeb;

            var rootWeb = (parentHost as SiteReverseHost).HostSite.RootWeb;
            var context = (parentHost as CSOMReverseHostBase).HostClientContext;


            //if (!web.IsObjectPropertyInstantiated("ServerRelativeUrl"))
            //{
            //    context.Load(web, w => w.ServerRelativeUrl);
            //    context.Load(rootWeb, w => w.ServerRelativeUrl);

            //    context.ExecuteQueryWithTrace();
            //}

            //var isRootWeb = web.ServerRelativeUrl == rootWeb.ServerRelativeUrl;

            //if (UseRootWebOnly && isRootWeb)
            //{
            //    return new[] { parentHost };
            //}

            var items = web.Webs;

            context.Load(items);
            context.ExecuteQueryWithTrace();

            result.AddRange(ApplyReverseFilters(items, options).ToArray().Select(i =>
            {
                return ModelHostBase.Inherit<WebReverseHost>(parentHost, h =>
                {
                    h.HostWeb = i;
                });
            }));

            TraceService.Information((int)ReverseLogEventId.ReverseHostsStart, "Processing web reverse host end");

            return result;
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as SecurityGroupReverseHost).HostGroup;

            var def = new SecurityGroupDefinition();

            def.Name = item.Title;
            def.Description = item.Description;

            return new SecurityGroupModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var typedHost = (reverseHost as TaxonomyTermStoreReverseHost);
            var item = typedHost.HostSite;

            var def = new TaxonomyTermStoreDefinition();

            def.UseDefaultSiteCollectionTermStore = true;

            return new TaxonomyTermStoreModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var typedHost = (reverseHost as ContentTypeLinkReverseHost);
            var item = typedHost.HostContentType;

            var def = new ContentTypeLinkDefinition();

            def.ContentTypeName = item.Name;

            return new ContentTypeLinkModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as TaxonomyFieldReverseHost).HostTaxonomyField;

            var def = new TaxonomyFieldDefinition();

            // TODO
            //def.Name = item.Name;

            return new TaxonomyFieldModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var web = (reverseHost as NavigationNodeReverseHost).HostWeb;

            var item = (reverseHost as NavigationNodeReverseHost).HostNavigationNode;
            var def = GetNavigationNodeDefinitionInstance();

            def.Title = item.Title;

            // should alway be web relative
            if (!web.IsObjectPropertyInstantiated("ServerRelativeUrl"))
            {
                web.Context.Load(web, w => w.ServerRelativeUrl);
                web.Context.ExecuteQueryWithTrace();
            }

            var webServerRelativeUrl = web.ServerRelativeUrl;
            var nodeServerRelativeUrl = item.Url;

            // roort web / ?
            if (webServerRelativeUrl.Length > 1)
            {
                nodeServerRelativeUrl = nodeServerRelativeUrl.Replace(webServerRelativeUrl, string.Empty);
            }

            def.Url = UrlUtility.RemoveStartingSlash(nodeServerRelativeUrl);
            def.IsExternal = item.IsExternal;

            if (def is QuickLaunchNavigationNodeDefinition)
            {
                return new QuickLaunchNavigationNodeModelNode
                {
                    Options = { RequireSelfProcessing = true },
                    Value = def
                };
            }
            else if (def is TopNavigationNodeDefinition)
            {
                return new TopNavigationNodeModelNode
                {
                    Options = { RequireSelfProcessing = true },
                    Value = def
                };
            }

            throw new SPMeta2ReverseException(string.Format("Navigation node definition of type:[{0}] is not supported",
                item.GetType()));
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as WikiPageReverseHost).HostWikiPageFile;

            var def = new WikiPageDefinition();

            def.FileName = item.Name;
            def.Content = ConvertUtils.ToString(item.ListItemAllFields[BuiltInInternalFieldNames.WikiField]);

            def.NeedOverride = true;

            return new WikiPageModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
        protected override void PostProcessFieldDefinitionInstance(FieldDefinition def, FieldReverseHost typedReverseHost, ReverseOptions options)
        {
            var context = typedReverseHost.HostClientContext;

            var typedField = context.CastTo<FieldUser>(typedReverseHost.Field);
            var typedDef = def.WithAssertAndCast<UserFieldDefinition>("modelHost", m => m.RequireNotNull());

            typedDef.Presence = typedField.Presence;

            if (typedField.SelectionGroup > 0)
            {
                typedDef.SelectionGroup = typedField.SelectionGroup;
            }

            typedDef.AllowDisplay = typedField.AllowDisplay;
            typedDef.SelectionMode = typedField.SelectionMode.ToString();
        }
        public override ModelNode ReverseSingleHost(object reverseHost, ReverseOptions options)
        {
            var item = (reverseHost as ContentTypeFieldLinkReverseHost).HostFieldLink;

            var def = new ContentTypeFieldLinkDefinition();

            def.FieldInternalName = item.Name;
            def.FieldId = item.Id;

            def.Hidden = item.Hidden;
            def.Required = item.Required;

            return new ContentTypeFieldLinkModelNode
            {
                Options = { RequireSelfProcessing = true },
                Value = def
            };
        }
 public abstract ReverseResult Reverse(object modelHost, ReverseOptions options);