private bool ContainsAncestor(FeatureExpressionInternal candidate, List <FeatureExpressionInternal> validFeature) { if (candidate.Source.Parent == null) { return(false); } if (validFeature.Any(valid => object.ReferenceEquals(valid.Source, candidate.Source.Parent))) { return(true); } var parent = this.allFeatures.First(f => object.ReferenceEquals(f.Source, candidate.Source.Parent)); return(ContainsAncestor(parent, validFeature)); }
/// <summary> /// Instantiate the meta information object such as <see cref="PreHashedFeature"/> /// for a given feature. /// </summary> /// <param name="featureInternal">The feature.</param> /// <param name="namespace">The namespace.</param> /// <returns>The "new" expression for the meta information object.</returns> private Expression CreateFeature(FeatureExpressionInternal featureInternal, Expression @namespace) { FeatureExpression feature = featureInternal.Source; var metaFeatureType = featureInternal.MarshalMethod.MetaFeatureType; if (metaFeatureType.IsGenericType && metaFeatureType.GetGenericTypeDefinition() == typeof(EnumerizedFeature <>)) { // preemptively calculate all hashes for each enum value var featureParameter = Expression.Parameter(metaFeatureType); var valueParameter = Expression.Parameter(feature.FeatureType); var body = new List <Expression>(); var hashVariables = new List <ParameterExpression>(); foreach (var value in Enum.GetValues(feature.FeatureType)) { var hashVar = Expression.Variable(typeof(UInt64)); hashVariables.Add(hashVar); // CODE hashVar = feature.FeatureHashInternal(value); body.Add(Expression.Assign(hashVar, Expression.Call(featureParameter, metaFeatureType.GetMethod("FeatureHashInternal"), Expression.Constant(value)))); } var cases = Enum.GetValues(feature.FeatureType) .Cast <object>() .Zip(hashVariables, (value, hash) => Expression.SwitchCase( hash, Expression.Constant(value, feature.FeatureType))) .ToArray(); // expand the switch(value) { case enum1: return hash1; .... } var hashSwitch = Expression.Switch(valueParameter, Expression.Block(Expression.Throw(Expression.New(typeof(NotSupportedException))), Expression.Constant((UInt64)0, typeof(UInt64))), cases); // CODE return value => switch(value) { .... } body.Add(Expression.Lambda(hashSwitch, valueParameter)); return(CreateNew( metaFeatureType, this.vwParameter, @namespace, Expression.Constant(feature.Name, typeof(string)), Expression.Constant(feature.AddAnchor), Expression.Constant(feature.Dictify), Expression.Lambda(Expression.Block(hashVariables, body), featureParameter))); } else if (metaFeatureType == typeof(PreHashedFeature)) { // CODE new PreHashedFeature(vw, namespace, "Name", "AddAnchor"); return(CreateNew( typeof(PreHashedFeature), this.vwParameter, @namespace, Expression.Constant(feature.Name, typeof(string)), Expression.Constant(feature.AddAnchor), Expression.Constant(feature.Dictify))); } else { // CODE new Feature("Name", ...) return(CreateNew( metaFeatureType, Expression.Constant(feature.Name, typeof(string)), Expression.Constant(feature.AddAnchor), Expression.Constant(feature.Dictify))); } }