Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
667a3d5
use Enum.Parse<TEnum>
lbargaoanu Jul 30, 2022
77086e8
less allocations
lbargaoanu Jul 31, 2022
e3aecd3
reuse the execution plan between user Map calls and internal Map calls
lbargaoanu Aug 1, 2022
6581906
remove IObjectMapperInfo
lbargaoanu Aug 2, 2022
5f0cebd
use the more efficient Expression.Invoke instead of ConvertReplacePar…
lbargaoanu Aug 3, 2022
9fc7cdf
less allocations
lbargaoanu Aug 3, 2022
7fdf915
less null checks
lbargaoanu Aug 4, 2022
4b507ee
unreachable, As maps are sealed by default
lbargaoanu Aug 6, 2022
84e3fff
less allocations
lbargaoanu Aug 6, 2022
b5cc0a6
don't try to match ignored members
lbargaoanu Aug 7, 2022
df48e72
more efficient
lbargaoanu Aug 7, 2022
12eaef9
drop RegEx
lbargaoanu Aug 8, 2022
06b0713
docs
lbargaoanu Aug 8, 2022
dc7e58f
cosmetic
lbargaoanu Aug 8, 2022
9356388
less allocations
lbargaoanu Aug 8, 2022
39fccd9
cosmetic
lbargaoanu Aug 9, 2022
a3ae964
less allocations
lbargaoanu Aug 9, 2022
00d29ee
we don't need to create As type maps
lbargaoanu Aug 11, 2022
c9bceef
remove ITypeMapConfiguration
lbargaoanu Aug 11, 2022
a0988d7
cosmetic
lbargaoanu Aug 11, 2022
0b9cf8c
try to show a better error message when mapping records through const…
lbargaoanu Aug 11, 2022
b9699dd
less allocations
lbargaoanu Aug 13, 2022
ed9097f
special case the defaults for naming conventions
lbargaoanu Aug 13, 2022
93576ef
make TypeMapPlanBuilder a struct
lbargaoanu Aug 15, 2022
3adb02f
use readonly record struct
lbargaoanu Aug 15, 2022
7720ac8
assume that a protected constructor with CompilerGeneratedAttribute m…
lbargaoanu Aug 15, 2022
4e1117f
less allocations
lbargaoanu Aug 15, 2022
dac3062
rename configurationProvider to the shorter configuration in most places
lbargaoanu Aug 17, 2022
b24560f
less allocations
lbargaoanu Aug 17, 2022
953d66d
converters with no source should throw
lbargaoanu Aug 17, 2022
ebd2c43
less allocations
lbargaoanu Aug 18, 2022
c5d7c36
cosmetic
lbargaoanu Aug 18, 2022
12676dd
less allocations
lbargaoanu Aug 19, 2022
85ff705
make MapFrom name more like the built-in mapping
lbargaoanu Aug 19, 2022
c71f168
less allocations
lbargaoanu Aug 20, 2022
3de255f
cosmetic
lbargaoanu Aug 21, 2022
6925737
use profiles in the benchmark
lbargaoanu Aug 21, 2022
08ec72a
simplify conventions
lbargaoanu Aug 21, 2022
e9287a2
merge the profile member configuration with the global one
lbargaoanu Aug 21, 2022
0d2aa50
cosmetic
lbargaoanu Aug 22, 2022
ec0a832
test reusing the execution plan
lbargaoanu Aug 22, 2022
593ad53
refactor test base classes
lbargaoanu Aug 22, 2022
806e73f
cosmetic
lbargaoanu Aug 23, 2022
d0e0e24
avoid changing the resolver configuration objects because they're reu…
lbargaoanu Aug 31, 2022
77e0015
cosmetic
lbargaoanu Aug 31, 2022
20c283a
less allocations
lbargaoanu Sep 3, 2022
66f0020
cosmetic
lbargaoanu Sep 3, 2022
f1655e1
file scoped namespaces
lbargaoanu Sep 3, 2022
288c4ad
global usings
lbargaoanu Sep 3, 2022
e6f2ca3
cosmetic
lbargaoanu Sep 4, 2022
daacd80
less allocations
lbargaoanu Sep 10, 2022
c608787
NullMappingOrderComesFirst
lbargaoanu Sep 10, 2022
434703c
less allocations
lbargaoanu Sep 10, 2022
4ba0e5f
we could include a different constructor
lbargaoanu Sep 10, 2022
b98273e
less allocations
lbargaoanu Sep 10, 2022
7eeaf59
cosmetic
lbargaoanu Sep 11, 2022
efd1df9
allocate _runtimeTypeDetails lazily
lbargaoanu Sep 12, 2022
3a491a3
create the projection builder lazily
lbargaoanu Sep 12, 2022
7da36f6
cosmetic
lbargaoanu Sep 12, 2022
970ab2d
an adhoc fix for including open generic config
lbargaoanu Sep 14, 2022
e7ba023
cosmetic
lbargaoanu Sep 18, 2022
2b99e96
MapFrom should override ignore
lbargaoanu Sep 18, 2022
3f8448a
UseDestinationValueNullable
lbargaoanu Sep 19, 2022
8b83aa7
cosmetic
lbargaoanu Sep 21, 2022
5e0066e
avoid LINQ
lbargaoanu Sep 23, 2022
7d65b78
the destination type name is already in the error message
lbargaoanu Sep 24, 2022
3c2d8cd
cosmetic
lbargaoanu Sep 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cosmetic
  • Loading branch information
lbargaoanu committed Aug 19, 2022
commit c5d7c364be400b7465d5749e068573bbe9a93d20
8 changes: 7 additions & 1 deletion src/AutoMapper/ApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ MembersMustExist : Member 'public System.String AutoMapper.LowerUnderscoreNaming
MembersMustExist : Member 'public System.Text.RegularExpressions.Regex AutoMapper.LowerUnderscoreNamingConvention.SplittingExpression.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.String AutoMapper.PascalCaseNamingConvention.ReplaceValue(System.Text.RegularExpressions.Match)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Text.RegularExpressions.Regex AutoMapper.PascalCaseNamingConvention.SplittingExpression.get()' does not exist in the implementation but it does exist in the contract.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'AutoMapper.Profile.DestinationMemberNamingConvention.get()' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'AutoMapper.Profile.DestinationMemberNamingConvention.set(AutoMapper.INamingConvention)' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'AutoMapper.Profile.SourceMemberNamingConvention.get()' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.CompilerGeneratedAttribute' exists on 'AutoMapper.Profile.SourceMemberNamingConvention.set(AutoMapper.INamingConvention)' in the contract but not the implementation.
MembersMustExist : Member 'public AutoMapper.IMappingOperationOptions AutoMapper.ResolutionContext.Options.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'AutoMapper.ValueResolverConfiguration' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Linq.Expressions.LambdaExpression System.Linq.Expressions.LambdaExpression AutoMapper.ValueTransformerConfiguration.TransformerExpression' does not exist in the implementation but it does exist in the contract.
Expand All @@ -46,6 +50,8 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMappe
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.UseExistingValueAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.ValueConverterAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.ValueResolverAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
MembersMustExist : Member 'public System.Collections.Generic.List<System.String> AutoMapper.Configuration.Conventions.PrePostfixName.Postfixes.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Collections.Generic.List<System.String> AutoMapper.Configuration.Conventions.PrePostfixName.Prefixes.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Linq.Expressions.Expression System.Linq.Expressions.Expression AutoMapper.Execution.Member.Expression' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Linq.Expressions.Expression System.Linq.Expressions.Expression AutoMapper.Execution.Member.Target' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Reflection.MemberInfo System.Reflection.MemberInfo AutoMapper.Execution.Member.MemberInfo' does not exist in the implementation but it does exist in the contract.
Expand Down Expand Up @@ -88,4 +94,4 @@ MembersMustExist : Member 'public AutoMapper.Internal.TypePair AutoMapper.Intern
MembersMustExist : Member 'public System.Linq.IQueryable<TDestination> AutoMapper.QueryableExtensions.Extensions.Map<TSource, TDestination>(System.Linq.IQueryable<TSource>, System.Linq.IQueryable<TDestination>, AutoMapper.IConfigurationProvider)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Collections.Generic.IReadOnlyCollection<System.Reflection.MemberInfo> AutoMapper.QueryableExtensions.MemberVisitor.MemberPath.get()' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'AutoMapper.QueryableExtensions.Impl.MemberAccessQueryMapperVisitor' does not exist in the implementation but it does exist in the contract.
Total Issues: 89
Total Issues: 95
17 changes: 1 addition & 16 deletions src/AutoMapper/Configuration/ConfigurationValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,23 @@
using AutoMapper.Internal.Mappers;
namespace AutoMapper.Configuration
{
using Validator = Action<ValidationContext>;
[EditorBrowsable(EditorBrowsableState.Never)]
public class ConfigurationValidator
{
private readonly IGlobalConfiguration _config;
private readonly IGlobalConfigurationExpression _expression;
private readonly Validator[] _validators;

public ConfigurationValidator(IGlobalConfiguration config, IGlobalConfigurationExpression expression)
{
_validators = expression.GetValidators();
_config = config;
_expression = expression;
}

private void Validate(ValidationContext context)
{
foreach (var validator in _validators)
foreach (var validator in _expression.GetValidators())
{
validator(context);
}
}

public void AssertConfigurationExpressionIsValid(IEnumerable<TypeMap> typeMaps)
{
if (!_expression.AllowAdditiveTypeMapCreation)
Expand All @@ -47,7 +41,6 @@ public void AssertConfigurationExpressionIsValid(IEnumerable<TypeMap> typeMaps)
}
AssertConfigurationIsValid(typeMaps);
}

public void AssertConfigurationIsValid(IEnumerable<TypeMap> typeMaps)
{
var maps = typeMaps as TypeMap[] ?? typeMaps.ToArray();
Expand All @@ -64,10 +57,8 @@ where unmappedPropertyNames.Length > 0 || !canConstruct
{
throw new AutoMapperConfigurationException(badTypeMaps);
}

var typeMapsChecked = new List<TypeMap>();
var configExceptions = new List<Exception>();

foreach (var typeMap in maps)
{
try
Expand All @@ -79,7 +70,6 @@ where unmappedPropertyNames.Length > 0 || !canConstruct
configExceptions.Add(e);
}
}

if (configExceptions.Count > 1)
{
throw new AggregateException(configExceptions);
Expand All @@ -89,7 +79,6 @@ where unmappedPropertyNames.Length > 0 || !canConstruct
throw configExceptions[0];
}
}

private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, TypePair types, TypeMap typeMap, MemberMap memberMap)
{
if(typeMap == null)
Expand All @@ -107,15 +96,12 @@ private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, TypePair types,
return;
}
typeMapsChecked.Add(typeMap);

var context = new ValidationContext(types, memberMap, typeMap);
Validate(context);

if(!typeMap.ShouldCheckForValid)
{
return;
}

CheckPropertyMaps(typeMapsChecked, typeMap);
}
else
Expand All @@ -133,7 +119,6 @@ private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, TypePair types,
}
}
}

private void CheckPropertyMaps(ICollection<TypeMap> typeMapsChecked, TypeMap typeMap)
{
foreach (var memberMap in typeMap.MemberMaps)
Expand Down
2 changes: 0 additions & 2 deletions src/AutoMapper/Configuration/Conventions/Mappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ public MemberInfo GetMatchingMemberInfo(TypeDetails sourceTypeDetails, Type dest
}
public class PrePostfixName : ISourceToDestinationNameMapper
{
public List<string> Prefixes { get; } = new();
public List<string> Postfixes { get; } = new();
public List<string> DestinationPrefixes { get; } = new();
public List<string> DestinationPostfixes { get; } = new();
public MemberInfo GetMatchingMemberInfo(TypeDetails sourceTypeDetails, Type destType, Type destMemberType, string nameToSearch)
Expand Down
27 changes: 4 additions & 23 deletions src/AutoMapper/Configuration/Conventions/MemberConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ public bool MapDestinationPropertyToSource(ProfileMap options, TypeDetails sourc
public class NameSplitMember : IChildMemberConfiguration
{
bool _default = true;
public INamingConvention SourceMemberNamingConvention { get; set; }
public INamingConvention DestinationMemberNamingConvention { get; set; }
public INamingConvention SourceMemberNamingConvention { get; set; } = PascalCaseNamingConvention.Instance;
public INamingConvention DestinationMemberNamingConvention { get; set; } = PascalCaseNamingConvention.Instance;
public bool MapDestinationPropertyToSource(ProfileMap options, TypeDetails sourceType, Type destType, Type destMemberType, string nameToSearch, List<MemberInfo> resolvers, IMemberConfiguration parent, bool isReverseMap) =>
_default ?
Default(options, sourceType, destType, destMemberType, nameToSearch, resolvers, parent, isReverseMap) :
Expand Down Expand Up @@ -143,26 +143,7 @@ bool Conventions(ProfileMap options, TypeDetails sourceType, Type destType, Type
}
return false;
}
internal void Set(INamingConvention source, INamingConvention destination)
{
if (source == null)
{
SourceMemberNamingConvention = PascalCaseNamingConvention.Instance;
}
else
{
SourceMemberNamingConvention = source;
_default = false;
}
if (destination == null)
{
DestinationMemberNamingConvention = PascalCaseNamingConvention.Instance;
}
else
{
DestinationMemberNamingConvention = destination;
_default = false;
}
}
internal void Seal() => _default = SourceMemberNamingConvention == PascalCaseNamingConvention.Instance &&
DestinationMemberNamingConvention == PascalCaseNamingConvention.Instance;
}
}
15 changes: 6 additions & 9 deletions src/AutoMapper/Configuration/MapperConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public class MapperConfiguration : IGlobalConfiguration
private readonly HashSet<TypeMap> _typeMapsPath = new();
private readonly List<MemberInfo> _sourceMembers = new();
private readonly List<ParameterExpression> _variables = new();
private readonly ParameterExpression[] _parameters = new ParameterExpression[] { null, null, ContextParameter };
private readonly ParameterExpression[] _parameters = new[] { null, null, ContextParameter };
private readonly CatchBlock[] _catches = new CatchBlock[1];
private readonly List<Expression> _expressions = new();
private readonly Dictionary<Type, DefaultExpression> _defaults;
Expand Down Expand Up @@ -165,9 +165,12 @@ Delegate CompileExecutionPlan(MapRequest mapRequest)
return executionPlan.Compile(); // breakpoint here to inspect all execution plans
}
}
public MapperConfiguration(Action<IMapperConfigurationExpression> configure)
: this(Build(configure))
public MapperConfiguration(Action<IMapperConfigurationExpression> configure) : this(Build(configure)){}
static MapperConfigurationExpression Build(Action<IMapperConfigurationExpression> configure)
{
MapperConfigurationExpression expr = new();
configure(expr);
return expr;
}
public void AssertConfigurationIsValid() => _validator.AssertConfigurationExpressionIsValid(_configuredMaps.Values);
public IMapper CreateMapper() => new Mapper(this);
Expand Down Expand Up @@ -242,12 +245,6 @@ LambdaExpression GenerateObjectMapperExpression(in MapRequest mapRequest, IObjec
return Lambda(fullExpression, source, destination, ContextParameter);
}
}
static MapperConfigurationExpression Build(Action<IMapperConfigurationExpression> configure)
{
var expr = new MapperConfigurationExpression();
configure(expr);
return expr;
}
IProjectionBuilder IGlobalConfiguration.ProjectionBuilder => _projectionBuilder;
Func<Type, object> IGlobalConfiguration.ServiceCtor => _serviceCtor;
bool IGlobalConfiguration.EnableNullPropagationForQueryMapping => _enableNullPropagationForQueryMapping;
Expand Down
6 changes: 3 additions & 3 deletions src/AutoMapper/Configuration/MapperConfigurationExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ public interface IMapperConfigurationExpression : IProfileExpression
}
public class MapperConfigurationExpression : Profile, IGlobalConfigurationExpression
{
private readonly List<Profile> _profiles = new List<Profile>();
private readonly List<Validator> _validators = new List<Validator>();
private readonly List<Profile> _profiles = new();
private readonly List<Validator> _validators = new();
private readonly List<IObjectMapper> _mappers;
private Func<Type, object> _serviceCtor = Activator.CreateInstance;

Expand All @@ -119,7 +119,7 @@ void IGlobalConfigurationExpression.Validator(Validator validator) =>
/// </summary>
int IGlobalConfigurationExpression.MaxExecutionPlanDepth { get; set; } = 1;

Validator[] IGlobalConfigurationExpression.GetValidators() => _validators.ToArray();
List<Validator> IGlobalConfigurationExpression.GetValidators() => _validators;

List<IProjectionMapper> IGlobalConfigurationExpression.ProjectionMappers { get; } = ProjectionBuilder.DefaultProjectionMappers();

Expand Down
39 changes: 23 additions & 16 deletions src/AutoMapper/Configuration/Profile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,28 @@ public interface IProfileConfiguration
/// </summary>
public abstract class Profile : IProfileExpressionInternal, IProfileConfiguration
{
private readonly List<string> _prefixes = new() { "Get" };
private readonly List<string> _postfixes = new();
private readonly List<TypeMapConfiguration> _typeMapConfigs = new();
private readonly PrePostfixName _prePostfixName = new();
private readonly List<IMemberConfiguration> _memberConfigurations = new();
private readonly NameSplitMember _nameSplitMember = new();
private readonly List<IMemberConfiguration> _memberConfigurations;
private List<Action<PropertyMap, IMemberConfigurationExpression>> _allPropertyMapActions;
private List<Action<TypeMap, IMappingExpression>> _allTypeMapActions;
private List<string> _globalIgnores;
private List<TypeMapConfiguration> _openTypeMapConfigs;
private List<MethodInfo> _sourceExtensionMethods;
private List<ValueTransformerConfiguration> _valueTransformerConfigs;
private bool? _constructorMappingEnabled;

protected Profile(string profileName) : this() => ProfileName = profileName;

protected Profile()
{
ProfileName = GetType().FullName;
var memberConfiguration = new MemberConfiguration();
memberConfiguration.MemberMappers.Add(new NameSplitMember());
_prePostfixName.Prefixes.Add("Get");
MemberConfiguration memberConfiguration = new() { MemberMappers = { _nameSplitMember } };
memberConfiguration.NameMapper.NamedMappers.Add(_prePostfixName);
_memberConfigurations.Add(memberConfiguration);
_memberConfigurations = new() { memberConfiguration };
}
protected Profile(string profileName, Action<IProfileExpression> configurationAction)
: this(profileName) => configurationAction(this);

protected Profile(string profileName, Action<IProfileExpression> configurationAction) : this(profileName) => configurationAction(this);
IMemberConfiguration DefaultMemberConfig => _memberConfigurations[0];
IMemberConfiguration IProfileExpressionInternal.DefaultMemberConfig => DefaultMemberConfig;
bool? IProfileConfiguration.ConstructorMappingEnabled => _constructorMappingEnabled;
Expand All @@ -114,10 +111,20 @@ IReadOnlyCollection<Action<PropertyMap, IMemberConfigurationExpression>> IProfil
public Func<FieldInfo, bool> ShouldMapField { get; set; }
public Func<MethodInfo, bool> ShouldMapMethod { get; set; }
public Func<ConstructorInfo, bool> ShouldUseConstructor { get; set; }
public INamingConvention SourceMemberNamingConvention { get; set; }
public INamingConvention DestinationMemberNamingConvention { get; set; }
public INamingConvention SourceMemberNamingConvention
{
get => _nameSplitMember.SourceMemberNamingConvention;
set => _nameSplitMember.SourceMemberNamingConvention = value;
}
public INamingConvention DestinationMemberNamingConvention
{
get => _nameSplitMember.DestinationMemberNamingConvention;
set => _nameSplitMember.DestinationMemberNamingConvention = value;
}
public List<ValueTransformerConfiguration> ValueTransformers => _valueTransformerConfigs ??= new();

NameSplitMember IProfileExpressionInternal.NameSplitMember => _nameSplitMember;
List<string> IProfileExpressionInternal.Prefixes => _prefixes;
List<string> IProfileExpressionInternal.Postfixes => _postfixes;
public void DisableConstructorMapping() => _constructorMappingEnabled = false;

void IProfileExpressionInternal.ForAllMaps(Action<TypeMap, IMappingExpression> configuration)
Expand Down Expand Up @@ -164,11 +171,11 @@ public IMappingExpression CreateMap(Type sourceType, Type destinationType, Membe
}
return map;
}
public void ClearPrefixes() => _prePostfixName.Prefixes.Clear();
public void ClearPrefixes() => _prefixes.Clear();
public void ReplaceMemberName(string original, string newValue) =>
DefaultMemberConfig.AddName<ReplaceName>(_ => _.AddReplace(original, newValue));
public void RecognizePrefixes(params string[] prefixes) => _prePostfixName.Prefixes.AddRange(prefixes);
public void RecognizePostfixes(params string[] postfixes) => _prePostfixName.Postfixes.AddRange(postfixes);
public void RecognizePrefixes(params string[] prefixes) => _prefixes.AddRange(prefixes);
public void RecognizePostfixes(params string[] postfixes) => _postfixes.AddRange(postfixes);
public void RecognizeDestinationPrefixes(params string[] prefixes) => _prePostfixName.DestinationPrefixes.AddRange(prefixes);
public void RecognizeDestinationPostfixes(params string[] postfixes) => _prePostfixName.DestinationPostfixes.AddRange(postfixes);
public void AddGlobalIgnore(string propertyNameStartingWith)
Expand Down
Loading