Stephen Stephen - 3 months ago 11
C# Question

What is preventing my collections from being mapped with AutoMapper (5.x)?

This one is going to require a bit of code , so here it goes. Given the following code, why is the Case Insureds collection not being mapped to the Request Insureds collection? I've spent the better part of the morning trying to get this to work.

Case classes:

using System;
using System.Collections.Generic;

namespace RequirementsWS.ServiceModel.Types
{
public class Case
{
public string BusinessArea { get; set; }

public string DistributionChannel { get; set; }

public string PolicyNumber { get; set; }

public bool JoinPolicyFlag { get; set; }

public decimal UWFaceAmount { get; set; }

public string ProductName { get; set; }

public string ProductFamily { get; set; }

public string WorkFlowProduct { get; set; }

public string AppState { get; set; }

public string ResidenceState { get; set; }

public string CaseSubType { get; set; }

public string OfficeNumber { get; set; }

public int ExternalCarrierCount { get; set; }

public bool ReplacementFlag { get; set; }

public bool Flag1035 { get; set; }

public bool EFTFLag { get; set; }

public bool TIAFlag { get; set; }

public bool QTAFlag { get; set; }

public bool InforceFlag { get; set; }

public bool CIRFlag { get; set; }

public bool BDRFlag { get; set; }

public bool ChildTermRiderFlag { get; set; }

public bool LTCRiderFlag { get; set; }

public bool PPWRiderFlag { get; set; }

public bool WGCFlag { get; set; }

public bool PremiumFinancingFlag { get; set; }

public bool QualifiedPlanFlag { get; set; }

public bool PremiumDepositFlag { get; set; }

public string Flag419E { get; set; }

public bool MECFlag { get; set; }

public bool DependentSupportFlag { get; set; }

public string UWDecision { get; set; }

public string ReissueReason { get; set; }

public string EFTType { get; set; }

public string PurposeofInsurance { get; set; }

public string ReplacementCoverageType { get; set; }

public string UnderwritingMethod { get; set; }

public bool NAICReqFlag { get; set; }

public bool CompareInfoFlag { get; set; }

public string CoverageType { get; set; }

public string ObjectID { get; set; }

public List<Insured> Insureds { get; } = new List<Insured>();

public List<Owner> Owners { get; } = new List<Owner>();

public List<Requirement> Requirements { get; } = new List<Requirement>();
}

public class Insured
{
public string InsuredID { get; set; }
public string InsuredRole { get; set; }
public int InsuredAge { get; set; }
public bool InsuredSmokerFlag { get; set; }
public bool JointInsured { get; set; }
public string RelationshipToInsured { get; set; }
public string State { get; set; }
public bool DependentForSupport { get; set; }

public string InsuredFirstName { get; set; }
public string InsuredMiddleInitial { get; set; }
public string InsuredLastName { get; set; }
public string InsuredSuffix { get; set; }
}

public class Owner
{
public string OwnerID { get; set; }
public string State { get; set; }
}

public enum WorkObjectState
{
None = 0,
Uncommited = 1,
Committed = 2
}

public enum AWDWorkType
{
None = 0,
NIGO = 1,
RISK = 2,
ISSUE = 3,
DELV = 4
}

public class Requirement
{
public WorkObjectState WorkObjectState { get; set; }

public string RequirementName { get; set; }
public AWDWorkType AWDWorkType { get; set; }
public string RequirementSubType { get; set; }
public string RequirementFulfiller { get; set; }

public string InsuredID { get; set; }
public string InsuredRole { get; set; }
public string InsuredFirstName { get; set; }
public string InsuredMiddleInitial { get; set; }
public string InsuredLastName { get; set; }
public string InsuredSuffix { get; set; }

public string InsuredFullName => $"{InsuredFirstName} {InsuredMiddleInitial} {InsuredLastName} {InsuredSuffix}";

//http://stackoverflow.com/questions/263400
//https://blogs.msdn.microsoft.com/ericlippert/2011/02/28/guidelines-and-rules-for-gethashcode/
//https://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

/// <summary>
/// Compare based on RequirementName, AWDWorkType, RequirementSubType, and InsuredID
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
Requirement right = obj as Requirement;
if (right == null)
{
return false;
}

if (RequirementName.Equals(right.RequirementName) &&
AWDWorkType.Equals(right.AWDWorkType) &&
RequirementSubType.Equals(right.RequirementSubType) &&
InsuredID.Equals(right.InsuredID))
{
return true;
}

return false;
}

public override int GetHashCode()
{
return new {RequirementName, AWDWorkType, RequirementSubType, InsuredID }.GetHashCode();
}

public override string ToString()
{
return base.ToString();
}
}

//https://msdn.microsoft.com/en-us/library/ms132151.aspx
//https://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

/// <summary>
/// Custom equality comparer
/// </summary>
public class RequirementEqualityComparer : IEqualityComparer<Requirement>
{
public bool Equals(Requirement left, Requirement right)
{
if (left == null && right == null)
{
return true;
}

if (left == null | right == null)
{
return false;
}

if (left.RequirementName == right.RequirementName &&
left.AWDWorkType == right.AWDWorkType &&
left.RequirementSubType == right.RequirementSubType &&
left.InsuredID == right.InsuredID)
{
return true;
}

return false;
}

public int GetHashCode(Requirement req)
{
return new { req.RequirementName, req.AWDWorkType, req.RequirementSubType, req.InsuredID }.GetHashCode();
}
}
}


Request classes:

namespace RequirementsWS.ServiceModel.Types.InRule.Requirements
{

/// <summary>Specifies the type of selection specified by the implementing attribute.</summary>
public enum InRuleImportAttributeType
{
Import,
Serializer,
Available,
Include,
IncludeMethods,
IncludeProperties,
IncludeFields,
IncludeBaseMethods,
RuleWrite,
RuleWriteAll,
}
/// <summary>Base class for InRule import attributes.</summary>
internal abstract class InRuleImportAttributeBase : System.Attribute
{
public abstract InRuleImportAttributeType InRuleImportAttributeType
{
get;
}
}
/// <summary>Indicates to the .NET Assembly Schema Importer that the decorated class should be selected.</summary>
internal class InRuleImportIncludeAttribute : InRuleImportAttributeBase
{
public virtual bool Include
{
get
{
return true;
}
}
public override InRuleImportAttributeType InRuleImportAttributeType
{
get
{
return InRuleImportAttributeType.Include;
}
}
}
}

using System.Xml.Serialization;

namespace RequirementsWS.ServiceModel.Types.InRule.Requirements
{
using System;
using System.Collections.Generic;

// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable]
public partial class PLRuleRequirement
{
private Response _response;
private Request _request;
public virtual Response Response
{
get
{
return this._response;
}
set
{
this._response = value;
}
}
public virtual Request Request
{
get
{
return this._request;
}
set
{
this._request = value;
}
}
}
// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable()]
public partial class Response
{
private List<Requirement> _requirements = new List<Requirement>();
public virtual List<Requirement> Requirements
{
get
{
return this._requirements;
}
}
}
// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable()]
public partial class Request
{
private string _objectID;
private string _businessArea;
private string _distributionChannel;
private string _policyNumber;
private decimal _uWFaceAmount;
private string _productName;
private string _productFamily;
private string _workFlowProduct;
private string _appState;
private List<Owner> _owners = new List<Owner>();
private List<Insured> _insureds = new List<Insured>();
private string _caseSubType;
private string _officeNumber;
private bool _replacementFlag;
private bool _flag1035;
private bool _tIAFlag;
private bool _inforceFlag;
private bool _cIRFlag;
private bool _bDRFlag;
private bool _childTermRiderFlag;
private bool _lTCRiderFlag;
private bool _pPWRiderFlag;
private bool _wGCFlag;
private bool _premiumFinancingFlag;
private bool _qualifiedPlanFlag;
private bool _premiumDepositFlag;
private bool _mECFlag;
private string _uWDecision;
private string _reissueReason;
private string _purposeofInsurance;
private string _replacementCoverageType;
private string _underwritingMethod;
private bool _nAICReqFlag;
private bool _compareInfoFlag;
public virtual string ObjectID
{
get
{
return this._objectID;
}
set
{
this._objectID = value;
}
}
public virtual string BusinessArea
{
get
{
return this._businessArea;
}
set
{
this._businessArea = value;
}
}
public virtual string DistributionChannel
{
get
{
return this._distributionChannel;
}
set
{
this._distributionChannel = value;
}
}
public virtual string PolicyNumber
{
get
{
return this._policyNumber;
}
set
{
this._policyNumber = value;
}
}
public virtual decimal UWFaceAmount
{
get
{
return this._uWFaceAmount;
}
set
{
this._uWFaceAmount = value;
}
}
public virtual string ProductName
{
get
{
return this._productName;
}
set
{
this._productName = value;
}
}
public virtual string ProductFamily
{
get
{
return this._productFamily;
}
set
{
this._productFamily = value;
}
}
public virtual string WorkFlowProduct
{
get
{
return this._workFlowProduct;
}
set
{
this._workFlowProduct = value;
}
}
public virtual string AppState
{
get
{
return this._appState;
}
set
{
this._appState = value;
}
}
public virtual List<Owner> Owners
{
get
{
return this._owners;
}
}
public virtual List<Insured> Insureds
{
get
{
return this._insureds;
}
}
public virtual string CaseSubType
{
get
{
return this._caseSubType;
}
set
{
this._caseSubType = value;
}
}
public virtual string OfficeNumber
{
get
{
return this._officeNumber;
}
set
{
this._officeNumber = value;
}
}
public virtual bool ReplacementFlag
{
get
{
return this._replacementFlag;
}
set
{
this._replacementFlag = value;
}
}
public virtual bool Flag1035
{
get
{
return this._flag1035;
}
set
{
this._flag1035 = value;
}
}
public virtual bool TIAFlag
{
get
{
return this._tIAFlag;
}
set
{
this._tIAFlag = value;
}
}
public virtual bool InforceFlag
{
get
{
return this._inforceFlag;
}
set
{
this._inforceFlag = value;
}
}
public virtual bool CIRFlag
{
get
{
return this._cIRFlag;
}
set
{
this._cIRFlag = value;
}
}
public virtual bool BDRFlag
{
get
{
return this._bDRFlag;
}
set
{
this._bDRFlag = value;
}
}
public virtual bool ChildTermRiderFlag
{
get
{
return this._childTermRiderFlag;
}
set
{
this._childTermRiderFlag = value;
}
}
public virtual bool LTCRiderFlag
{
get
{
return this._lTCRiderFlag;
}
set
{
this._lTCRiderFlag = value;
}
}
public virtual bool PPWRiderFlag
{
get
{
return this._pPWRiderFlag;
}
set
{
this._pPWRiderFlag = value;
}
}
public virtual bool WGCFlag
{
get
{
return this._wGCFlag;
}
set
{
this._wGCFlag = value;
}
}
public virtual bool PremiumFinancingFlag
{
get
{
return this._premiumFinancingFlag;
}
set
{
this._premiumFinancingFlag = value;
}
}
public virtual bool QualifiedPlanFlag
{
get
{
return this._qualifiedPlanFlag;
}
set
{
this._qualifiedPlanFlag = value;
}
}
public virtual bool PremiumDepositFlag
{
get
{
return this._premiumDepositFlag;
}
set
{
this._premiumDepositFlag = value;
}
}
public virtual bool MECFlag
{
get
{
return this._mECFlag;
}
set
{
this._mECFlag = value;
}
}
public virtual string UWDecision
{
get
{
return this._uWDecision;
}
set
{
this._uWDecision = value;
}
}
public virtual string ReissueReason
{
get
{
return this._reissueReason;
}
set
{
this._reissueReason = value;
}
}
public virtual string PurposeofInsurance
{
get
{
return this._purposeofInsurance;
}
set
{
this._purposeofInsurance = value;
}
}
public virtual string ReplacementCoverageType
{
get
{
return this._replacementCoverageType;
}
set
{
this._replacementCoverageType = value;
}
}
public virtual string UnderwritingMethod
{
get
{
return this._underwritingMethod;
}
set
{
this._underwritingMethod = value;
}
}
public virtual bool NAICReqFlag
{
get
{
return this._nAICReqFlag;
}
set
{
this._nAICReqFlag = value;
}
}
public virtual bool CompareInfoFlag
{
get
{
return this._compareInfoFlag;
}
set
{
this._compareInfoFlag = value;
}
}
}
// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable()]
public partial class Requirement
{
private string _requirementName;
private string _requirementType;
private string _insuredRole;
private string _insuredID;
private string _subType;
public virtual string RequirementName
{
get
{
return this._requirementName;
}
set
{
this._requirementName = value;
}
}
public virtual string RequirementType
{
get
{
return this._requirementType;
}
set
{
this._requirementType = value;
}
}
public virtual string InsuredRole
{
get
{
return this._insuredRole;
}
set
{
this._insuredRole = value;
}
}
public virtual string InsuredID
{
get
{
return this._insuredID;
}
set
{
this._insuredID = value;
}
}
public virtual string SubType
{
get
{
return this._subType;
}
set
{
this._subType = value;
}
}
}
// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable()]
public partial class Insured
{
private string _insuredID;
private string _insuredRole;
private int _insuredAge;
private bool _insuredSmokerFlag;
private bool _jointInsured;
private string _relationshipToInsured;
private string _state;
private bool _dependentForSupport;
public virtual string InsuredID
{
get
{
return this._insuredID;
}
set
{
this._insuredID = value;
}
}
public virtual string InsuredRole
{
get
{
return this._insuredRole;
}
set
{
this._insuredRole = value;
}
}
public virtual int InsuredAge
{
get
{
return this._insuredAge;
}
set
{
this._insuredAge = value;
}
}
public virtual bool InsuredSmokerFlag
{
get
{
return this._insuredSmokerFlag;
}
set
{
this._insuredSmokerFlag = value;
}
}
public virtual bool JointInsured
{
get
{
return this._jointInsured;
}
set
{
this._jointInsured = value;
}
}
public virtual string RelationshipToInsured
{
get
{
return this._relationshipToInsured;
}
set
{
this._relationshipToInsured = value;
}
}
public virtual string State
{
get
{
return this._state;
}
set
{
this._state = value;
}
}
public virtual bool DependentForSupport
{
get
{
return this._dependentForSupport;
}
set
{
this._dependentForSupport = value;
}
}
}
// NOTE: This class was automatically generated by InRule irAuthor
// and may be overwritten in the future.
// Consider creating a matching partial class if modifications are required.
[InRuleImportInclude()]
[Serializable()]
public partial class Owner
{
private string _ownerID;
private string _state;
public virtual string OwnerID
{
get
{
return this._ownerID;
}
set
{
this._ownerID = value;
}
}
public virtual string State
{
get
{
return this._state;
}
set
{
this._state = value;
}
}
}
}


Program classes:

class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg =>
{
cfg.ShouldMapField = fi => false;
cfg.ShouldMapProperty = pi => pi.GetMethod != null && (pi.GetMethod.IsPublic || pi.GetMethod.IsVirtual);

cfg.CreateMap<RequirementsWS.ServiceModel.Types.Owner, RequirementsWS.ServiceModel.Types.InRule.Requirements.Owner>()
.ReverseMap();

cfg.CreateMap<RequirementsWS.ServiceModel.Types.Insured, RequirementsWS.ServiceModel.Types.InRule.Requirements.Insured>()
.ReverseMap();

cfg.CreateMap<RequirementsWS.ServiceModel.Types.Case, RequirementsWS.ServiceModel.Types.InRule.Requirements.Request>();
});

config.AssertConfigurationIsValid();

IMapper mapper = config.CreateMapper();

RequirementsWS.ServiceModel.Types.Case @case = new RequirementsWS.ServiceModel.Types.Case();
@case.AppState = "CA";

RequirementsWS.ServiceModel.Types.Insured insured = new RequirementsWS.ServiceModel.Types.Insured();
insured.InsuredID = Guid.NewGuid().ToString("N");
insured.State = "AR";

@case.Insureds.Add(insured);

RequirementsWS.ServiceModel.Types.InRule.Requirements.Request result =
mapper.Map<RequirementsWS.ServiceModel.Types.Case, RequirementsWS.ServiceModel.Types.InRule.Requirements.Request>(@case);

Debug.Assert(result != null);
Debug.Assert(result.AppState.Equals(@case.AppState));
Debug.Assert(result.Insureds != null);
Debug.Assert(result.Insureds.Count > 0);
Debug.Assert(result.Insureds[0].InsuredID.Equals(insured.InsuredID));
Debug.Assert(result.Insureds[0].State.Equals(insured.State));

Console.WriteLine("Finished");
Console.ReadKey();
}
}


Thank you,
Stephen

Answer

Request.Insureds has no setter (not even a private one) so AutoMapper can't do anything with it. Its easily fixed by adding a private setter (since it then can be set via reflection).

    public virtual List<Insured> Insureds {
        get {
            return this._insureds;
        }
        set {
            this._insureds = value;
        }
    }

This of course goes for all your collections on the request object, without any type of setter they won't be mapped.