in Cognitive Services/CSharp/Library/LuisActionBinding/LuisActionResolver.cs [548:677]
private static bool AssignEntitiesToMembers(
ILuisAction action,
IEnumerable<PropertyInfo> properties,
IEnumerable<EntityRecommendation> entities,
Func<PropertyInfo, IEnumerable<EntityRecommendation>, EntityRecommendation> entityExtractor = null)
{
var result = true;
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
if (properties == null)
{
throw new ArgumentNullException(nameof(properties));
}
if (entities == null)
{
throw new ArgumentNullException(nameof(entities));
}
if (!entities.Any())
{
return !result;
}
// Cross match entities to copy resolution values for custom entities from pairs
foreach (var group in entities.GroupBy(e => e.Entity))
{
if (group.Count() > 1)
{
var entityToUpdate = group.FirstOrDefault(e => !BuiltInTypes.IsBuiltInType(e.Type));
var entityWithValue = group.FirstOrDefault(e => e.Resolution != null);
if (entityToUpdate != null && entityWithValue != null)
{
entityToUpdate.Resolution = entityWithValue.Resolution;
}
}
}
foreach (var property in properties)
{
var matchingEntity = default(EntityRecommendation);
var matchingEntities = default(IEnumerable<EntityRecommendation>);
// Find using custom type from attrib if available
var paramAttrib = property.GetCustomAttributes<LuisActionBindingParamAttribute>(true).FirstOrDefault();
if (paramAttrib != null)
{
matchingEntities = entities.Where(e => e.Type == paramAttrib.CustomType);
}
// Find using property name
if (matchingEntities == null || !matchingEntities.Any())
{
matchingEntities = entities.Where(e => e.Type == property.Name);
}
// Find using builtin type from attrib if available
if ((matchingEntities == null || !matchingEntities.Any()) && paramAttrib != null)
{
matchingEntities = entities.Where(e => e.Type == paramAttrib.BuiltinType);
}
// If callback available then use it
if (matchingEntities.Count() > 1)
{
if (entityExtractor != null)
{
matchingEntity = entityExtractor(property, matchingEntities);
}
}
else
{
matchingEntity = matchingEntities.FirstOrDefault();
}
// Prioritize resolution
if (matchingEntity != null)
{
object paramValue = null;
if (matchingEntity.Resolution != null && matchingEntity.Resolution.Count > 0)
{
var resolutionValue = matchingEntity.Resolution.First().Value;
if (resolutionValue is IList<object>)
{
// multiple resolution values - datetimev2
var dateTimeResolutionValues = GetDateTimeValues(matchingEntity);
paramValue = dateTimeResolutionValues["value"];
}
if (paramValue == null)
{
// other built-in with single resolution value
paramValue = resolutionValue;
}
}
else
{
paramValue = matchingEntity.Entity;
}
result &= AssignValue(action, property, paramValue);
}
else if (matchingEntities.Count() > 0
&& matchingEntities.Count(e => e.Resolution != null && e.Resolution.First().Value is JArray) == matchingEntities.Count())
{
var paramValues = new JArray();
foreach (var currentMatchingEntity in matchingEntities)
{
var values = currentMatchingEntity.Resolution.First().Value as JArray;
foreach (var value in values)
{
paramValues.Add(value);
}
}
result &= AssignValue(action, property, paramValues);
}
else
{
result = false;
}
}
return result;
}