public void GetPolicy_Returns_SpecifiedPolicy() { PropertyInfo propInfo = typeof(AttributeWithResolutionPolicy).GetProperty(nameof(AttributeWithResolutionPolicy.PropWithPolicy)); IResolutionPolicy policy = AttributeCloner <AttributeWithResolutionPolicy> .GetPolicy(propInfo); Assert.IsType <TestResolutionPolicy>(policy); }
public void GetPolicy_ReturnsDefault_WhenNoSpecifiedPolicy() { PropertyInfo propInfo = typeof(AttributeWithResolutionPolicy).GetProperty(nameof(AttributeWithResolutionPolicy.PropWithoutPolicy)); AutoResolveAttribute attr = propInfo.GetCustomAttribute <AutoResolveAttribute>(); IResolutionPolicy policy = AttributeCloner <AttributeWithResolutionPolicy> .GetPolicy(attr.ResolutionPolicyType, propInfo); Assert.IsType <DefaultResolutionPolicy>(policy); }
private static string TemplateBind(IResolutionPolicy policy, PropertyInfo prop, Attribute attr, BindingTemplate template, IReadOnlyDictionary <string, object> bindingData) { if (bindingData == null) { return(template?.Pattern); } return(policy.TemplateBind(prop, attr, template, bindingData)); }
// AutoResolve internal static BindingDataResolver GetTemplateResolver(string originalValue, AutoResolveAttribute attr, INameResolver nameResolver, PropertyInfo propInfo, BindingDataContract contract) { string resolvedValue = nameResolver.ResolveWholeString(originalValue); var template = BindingTemplate.FromString(resolvedValue); IResolutionPolicy policy = GetPolicy(attr.ResolutionPolicyType, propInfo); template.ValidateContractCompatibility(contract); return((newAttr, bindingData) => TemplateBind(policy, propInfo, newAttr, template, bindingData)); }
public void GetPolicy_ReturnsODataFilterPolicy_ForMarkerType() { // This is a special-case marker type to handle TableAttribute.Filter. We cannot directly list ODataFilterResolutionPolicy // because BindingTemplate doesn't exist in the core assembly. PropertyInfo propInfo = typeof(AttributeWithResolutionPolicy).GetProperty(nameof(AttributeWithResolutionPolicy.PropWithMarkerPolicy)); IResolutionPolicy policy = AttributeCloner <AttributeWithResolutionPolicy> .GetPolicy(propInfo); Assert.IsType <Host.Bindings.ODataFilterResolutionPolicy>(policy); }
private static string TemplateBind(IResolutionPolicy policy, PropertyInfo prop, Attribute attr, BindingTemplate template, BindingData bindingData, Validator validator) { if (bindingData == null) { // Skip validation if no binding data provided. We can't do the { } substitutions. return(template?.Pattern); } var newValue = policy.TemplateBind(prop, attr, template, bindingData); validator(newValue); return(newValue); }
// AutoResolve internal static BindingDataResolver GetTemplateResolver(string originalValue, AutoResolveAttribute attr, INameResolver nameResolver, PropertyInfo propInfo, BindingDataContract contract, Validator validator) { string resolvedValue = nameResolver.ResolveWholeString(originalValue); var template = BindingTemplate.FromString(resolvedValue); if (!template.HasParameters) { // No { } tokens, bind eagerly up front. validator(resolvedValue); } IResolutionPolicy policy = GetPolicy(attr.ResolutionPolicyType, propInfo); template.ValidateContractCompatibility(contract); return((newAttr, bindingData) => TemplateBind(policy, propInfo, newAttr, template, bindingData, validator)); }
public AttributeCloner( TAttribute source, IReadOnlyDictionary <string, Type> bindingDataContract, INameResolver nameResolver = null, Func <TAttribute, Task <TAttribute> > hook = null) { _hook = hook; nameResolver = nameResolver ?? new EmptyNameResolver(); _source = source; Type t = typeof(TAttribute); Dictionary <string, PropertyInfo> availableParams = new Dictionary <string, PropertyInfo>(StringComparer.OrdinalIgnoreCase); foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var objValue = prop.GetValue(_source); if (objValue != null) { availableParams[prop.Name] = prop; } } int longestMatch = -1; // Pick the ctor with the longest parameter list where all parameters are matched. var ctors = t.GetConstructors(BindingFlags.Public | BindingFlags.Instance); foreach (var ctor in ctors) { var ps = ctor.GetParameters(); int len = ps.Length; var getArgFuncs = new Func <IReadOnlyDictionary <string, object>, object> [len]; bool hasAllParameters = true; for (int i = 0; i < len; i++) { var p = ps[i]; PropertyInfo propInfo = null; if (!availableParams.TryGetValue(p.Name, out propInfo)) { hasAllParameters = false; break; } BindingTemplate template; if (TryCreateAutoResolveBindingTemplate(propInfo, nameResolver, out template)) { IResolutionPolicy policy = GetPolicy(propInfo); template.ValidateContractCompatibility(bindingDataContract); getArgFuncs[i] = (bindingData) => TemplateBind(policy, propInfo, source, template, bindingData); } else { var propValue = propInfo.GetValue(_source); getArgFuncs[i] = (bindingData) => propValue; } } if (hasAllParameters) { if (len > longestMatch) { var setProperties = new List <Action <TAttribute, IReadOnlyDictionary <string, object> > >(); // Record properties too. foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (!prop.CanWrite) { continue; } BindingTemplate template; if (TryCreateAutoResolveBindingTemplate(prop, nameResolver, out template)) { IResolutionPolicy policy = GetPolicy(prop); template.ValidateContractCompatibility(bindingDataContract); setProperties.Add((newAttr, bindingData) => prop.SetValue(newAttr, TemplateBind(policy, prop, newAttr, template, bindingData))); } else { var objValue = prop.GetValue(_source); setProperties.Add((newAttr, bindingData) => prop.SetValue(newAttr, objValue)); } } _setProperties = setProperties.ToArray(); _bestCtor = ctor; longestMatch = len; _bestCtorArgBuilder = getArgFuncs; } } } if (_bestCtor == null) { // error!!! throw new InvalidOperationException("Can't figure out which ctor to call."); } }