You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi. Seems that there is an issue with Compile() call.
Mapster is modifying collection when it's being iterated.
The problem happens when there is top level mapping defined between objects, but nested property ( usually a collection of some type) is not defined explicitly).
If List<SrcItem> -> List<DestItem> is commented out - it throws vague InvalidOperationException: Collection was modified; enumeration operation may not execute.
This happens because TypeAdapterConfig.GetSettings(x) is not safe - it modifies collection this.RuleMap that is being iterated in TypeAdapterConfig.Compile() call.
// public class TypeAdapterConfig
//...
private TypeAdapterSettings GetSettings(TypeTuple key)
{
TypeAdapterRule typeAdapterRule;
if (!this.RuleMap.TryGetValue(key, out typeAdapterRule))
{
lock (this.RuleMap)
{
if (!this.RuleMap.TryGetValue(key, out typeAdapterRule))
{
typeAdapterRule = key.Source == typeof (void) ? TypeAdapterConfig.CreateDestinationTypeRule(key) : this.CreateTypeTupleRule(key);
this.Rules.Add(typeAdapterRule); // <----------- modifies collection on Read this.RuleMap.Add(key, typeAdapterRule); // <----------- modifies collection on Read which is being iterated in Compile()
}
}
}
return typeAdapterRule.Settings;
}
Here is bug repro example (works well in LinqPad with Mapster and AutoFixture nugets but can be easily converted to a console app):
void Main()
{
WebDTOMapSetup.Verify();
var fixt = new Fixture();
var input = fixt.Create<MainSrc>();
var output = input.Adapt<MainSrc,MainDest>();
output.Dump();
}
public class WebDTOMapSetup
{
static WebDTOMapSetup()
{
configme();
}
private static void configme()
{
TypeAdapterConfig<SrcItem, DestItem>.ForType();
// BUG TRIGGER IS HERE --------> Comment this line to see mapster bug
TypeAdapterConfig<List<SrcItem>, List<DestItem>>.ForType();
//Validate globally
TypeAdapterConfig<MainSrc, MainDest>.ForType()
.Map(d=>d.DestItems, s=>s.SrcItems)
;
TypeAdapterConfig.GlobalSettings.Compile();
}
public static void Verify()
{
TypeAdapterConfig.GlobalSettings.Compile();
}
}
class MainSrc
{
public int SrcId { get; set; }
public List<SrcItem> SrcItems { get; set; }
}
class MainDest
{
public int DestId { get; set; }
public List<DestItem> DestItems { get; set; }
}
class SrcItem
{
public int ItemId { get; set; }
public string StringData { get; set; }
}
class DestItem
{
public int ItemId { get; set; }
public string StringData { get; set; }
}
The text was updated successfully, but these errors were encountered:
I'm not sure how exactly it should be fixed, maybe by copying collection before iteration.
If it's by design - it will force everyone to define all possible combinations of collection mappings which kind of defeats the purpose of the mapping itself...
Hi. Seems that there is an issue with Compile() call.
Mapster is modifying collection when it's being iterated.
The problem happens when there is top level mapping defined between objects, but nested property ( usually a collection of some type) is not defined explicitly).
For the code below:
If I have 3 mappings defined:
In this case Compile works perfectly
If
List<SrcItem> -> List<DestItem>
is commented out - it throws vagueInvalidOperationException: Collection was modified; enumeration operation may not execute.
This happens because
TypeAdapterConfig.GetSettings(x)
is not safe - it modifies collectionthis.RuleMap
that is being iterated inTypeAdapterConfig.Compile()
call.Here is bug repro example (works well in LinqPad with Mapster and AutoFixture nugets but can be easily converted to a console app):
The text was updated successfully, but these errors were encountered: