Skip to content

Commit 359eaae

Browse files
committed
Introduce SetItemCompatibility() method in TypeAccessor
While the `MaybeCompatible` property is the main interface for determining compatibility when calling into `TypeAccessor` (6662e18), the business logic for determining what may or may not be compatible is handled by `TypeAccessor`. The `SetItemCompatibility()` is a private helper method called by the constructor to set `MaybeCompatible` on both `MemberAccessor` and `ParameterMetadata` instances. This addresses the core functionality of #102.
1 parent 6662e18 commit 359eaae

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

OnTopic/Internal/Reflection/TypeAccessor.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ internal TypeAccessor(Type type) {
9090
ConstructorParameters.Add(new(parameter));
9191
}
9292

93+
/*------------------------------------------------------------------------------------------------------------------------
94+
| Identify expected topic, and set MaybeCompatible if a corresponding property exists
95+
\-----------------------------------------------------------------------------------------------------------------------*/
96+
SetItemCompatibility();
97+
9398
}
9499

95100
/*==========================================================================================================================
@@ -390,5 +395,62 @@ internal void SetPropertyValue(object target, string propertyName, object? value
390395
internal void SetMethodValue(object target, string methodName, object? value, bool allowConversion = false)
391396
=> SetValue(target, methodName, value, allowConversion);
392397

398+
/*==========================================================================================================================
399+
| METHOD: SET ITEM COMPATIBILITY
400+
\-------------------------------------------------------------------------------------------------------------------------*/
401+
/// <summary>
402+
/// Determines if each member corresponds to a compatible or convertible member of a corresponding <see cref="Topic"/>.
403+
/// </summary>
404+
/// <remarks>
405+
/// The <see cref="SetItemCompatibility"/> method applies basic assumptions to identify the corresponding <see cref=
406+
/// "Topic"/> and whether or not any matching parameters or members are compatible with members of that <see cref="Topic"
407+
/// />. See <see cref="ItemMetadata.MaybeCompatible"/> for more details.
408+
/// </remarks>
409+
private void SetItemCompatibility() {
410+
411+
/*------------------------------------------------------------------------------------------------------------------------
412+
| Only attempt to detect compatibility for model types, not for topics.
413+
>-------------------------------------------------------------------------------------------------------------------------
414+
| We expect mapping to topics to typically use e.g. Attributes or References, which will automatically marshal through
415+
| properties if appropriate.
416+
\-----------------------------------------------------------------------------------------------------------------------*/
417+
if (typeof(Topic).IsAssignableFrom(Type)) {
418+
return;
419+
}
420+
421+
/*------------------------------------------------------------------------------------------------------------------------
422+
| Identify corresponding topic type
423+
>-------------------------------------------------------------------------------------------------------------------------
424+
| Assuming a model follows the convention {ContentType}TopicViewModel or {ContentType}ViewModel, find a corresponding
425+
| Topic named {ContentType}. If this cannot be found, fall back to Topic.
426+
\-----------------------------------------------------------------------------------------------------------------------*/
427+
var impliedContentType = Type.Name
428+
.Replace("TopicViewModel", "", StringComparison.OrdinalIgnoreCase)
429+
.Replace("ViewModel", "", StringComparison.OrdinalIgnoreCase);
430+
var topicType = TopicFactory.TypeLookupService.Lookup(impliedContentType)?? typeof(Topic);
431+
var topicAccessor = TypeAccessorCache.GetTypeAccessor(topicType);
432+
433+
/*------------------------------------------------------------------------------------------------------------------------
434+
| Detect compatibility
435+
>-------------------------------------------------------------------------------------------------------------------------
436+
| If the Topic contains a property named {Name} or a method named Get{Name}, and that member's type is either compatible
437+
| or convertible, then set MaybeCompatible to true.
438+
\-----------------------------------------------------------------------------------------------------------------------*/
439+
foreach (var member in ConstructorParameters.Cast<ItemMetadata>().Union(_members.Values)) {
440+
var attributeKey = member.Configuration.AttributeKey;
441+
var topicMember = topicAccessor.GetMember(attributeKey)?? topicAccessor.GetMember($"Get{attributeKey}");
442+
if (topicMember is null) {
443+
continue;
444+
}
445+
else if (member.IsConvertible && topicMember.Type == typeof(string)) {
446+
member.MaybeCompatible = true;
447+
}
448+
else if (member.Type.IsAssignableFrom(topicMember.Type)) {
449+
member.MaybeCompatible = true;
450+
}
451+
452+
}
453+
}
454+
393455
} //Class
394456
} //Namespace

0 commit comments

Comments
 (0)