---
title: Map resource or view-model properties
summary: Uses reflection to copy public properties of a matching type from a newly constructed source instance onto a newly constructed destination instance, or to emit VB property-declaration scaffolding for matching properties.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Resources
reference_type: package
operation_id: OP-RES-04
trigger: Caller invokes ResourceViewModelMapper.Map or ResourceViewModelMapper.GetViewModelProperties
---

# 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.
   - If a same-named, same-typed source value was collected: the value is written onto the destination property via `SetValue`.
   - If no matching source pair exists: the destination property is left at its default-constructed value.
4. **Return the mapped destination.** `Map` returns the destination instance, cast to `TDestination`.
5. **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`.

```mermaid
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.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `Resources\SAIF.Resources\Mappings\ResourceViewModelMapper.vb`
