Skip to content

Map resource or view-model properties

ResourceViewModelMapper is a reflection-based helper used to project properties of one type — typically a generated resource class — onto another type, such as a view model, by matching on both property name and property type. A related pair of overloads instead emits generated VB.NET property-declaration source text for scaffolding a destination type, rather than performing a live copy.

Field Value
Operation ID OP-RES-04
Trigger Caller invokes the shared generic method ResourceViewModelMapper.Map(Of TSource, TDestination, TPropertyType)(), or one of the GetViewModelProperties overloads
Inputs Source type, destination type, and the property type to match on (as generic type parameters, or as Type arguments for the non-generic GetViewModelProperties overload)
Outputs A new TDestination instance with matching properties copied from a new TSource instance (Map), or a string of generated Public Property ... As String = "..." declarations (GetViewModelProperties)
Primary components ResourceViewModelMapper.Map, ResourceViewModelMapper.GetViewModelProperties
Entry point Resources\SAIF.Resources\Mappings\ResourceViewModelMapper.vb

Steps

  1. Construct source and destination instances. Map uses Activator.CreateInstance(GetType(TSource), True) and Activator.CreateInstance(GetType(TDestination), True) to create new instances of both generic type arguments, including via non-public constructors.
  2. Collect matching source properties. Map enumerates TSource's public properties, keeping only those whose PropertyType is exactly TPropertyType, and records each property's name and current value (read from the freshly constructed source instance) as a name/value pair.
  3. Copy into matching destination properties. Map enumerates TDestination's public properties, again filtering to those whose PropertyType is exactly TPropertyType. For each destination property, it looks up a collected source pair with the same name.
  4. If a same-named, same-typed source value was collected: the value is written onto the destination property via SetValue.
  5. If no matching source pair exists: the destination property is left at its default-constructed value.
  6. Return the mapped destination. Map returns the destination instance, cast to TDestination.
  7. Alternative: emit scaffolding source instead of mapping. GetViewModelProperties(Of TSource, TPropertyType)() (or its non-generic Type-based overload) constructs a single TSource instance, enumerates its properties matching TPropertyType, and appends one Public Property {Name} As String = "{Value}" line per match to a StringBuilder, returning the generated text instead of a live object.

Process flow

The following diagram visualizes the property-matching copy performed by Map.

flowchart TD
    Start([Caller calls Map]) --> CreateSrc[Construct new TSource instance]
    CreateSrc --> CreateDst[Construct new TDestination instance]
    CreateDst --> CollectSrc[Collect TSource properties<br>matching TPropertyType]
    CollectSrc --> LoopDst[Iterate TDestination properties<br>matching TPropertyType]
    LoopDst --> NameMatch{Same-named source<br>value collected?}
    NameMatch -->|Yes| SetValue[Write value onto<br>destination property]
    NameMatch -->|No| Skip[Leave destination property<br>at default value]
    SetValue --> More{More destination<br>properties?}
    Skip --> More
    More -->|Yes| LoopDst
    More -->|No| Return([Return destination instance])

Failure and edge-case behavior

  • Both TSource and TDestination must be constructible via Activator.CreateInstance(..., True); a type without an accessible or parameterless (including non-public) constructor causes the call to fail.*
  • Matching requires an exact property-type match (Is) against TPropertyType, so properties of a compatible but non-identical type (e.g., a subclass) are not considered a match.
  • Matching also requires an exact, case-sensitive name match between source and destination properties; a destination property with no equivalently named/typed source property is left unset rather than raising an error.
  • Map always constructs fresh TSource and TDestination instances — it does not accept pre-existing instances to map from or into.
  • GetViewModelProperties reads the source instance's current (default-constructed) values only, so it is useful for scaffolding initial property declarations rather than for capturing a specific runtime state.*

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • Resources\SAIF.Resources\Mappings\ResourceViewModelMapper.vb