Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IgnoreCase NameMatchingStrategy #88

Closed
cbrgray opened this issue Nov 1, 2016 · 1 comment
Closed

IgnoreCase NameMatchingStrategy #88

cbrgray opened this issue Nov 1, 2016 · 1 comment

Comments

@cbrgray
Copy link

cbrgray commented Nov 1, 2016

It looks like there's no functionality to map differently cased fields with without underscores.

For example, using the Flexible strategy, FOOBAR will map to Foobar, but not FooBar. This is due to it being treated as one word for PascalCase matching. Not sure if it was intentionally excluded or is already possible somehow, but it would be useful IMO to have an IgnoreCase matching strategy, which would match FOOBAR to FooBar, fOObAR, foobar etc.

I've implemented this on my build, and it seems to be a fairly simple addition. However, I'm unaware of how it might affect performance, other than OrdinalIgnoreCase giving a faster string comparison.

In NameMatchingStrategy.cs, add an IgnoreCase property:

public bool? IgnoreCase { get; set; }

public void Apply(NameMatchingStrategy other)
{
    if (this.SourceMemberNameConverter == null)
        this.SourceMemberNameConverter = other.SourceMemberNameConverter;
    if (this.DestinationMemberNameConverter == null)
        this.DestinationMemberNameConverter = other.DestinationMemberNameConverter;
    if (this.IgnoreCase == null)
        this.IgnoreCase = other.IgnoreCase;
}

public static readonly NameMatchingStrategy Exact = new NameMatchingStrategy(Identity, Identity);
public static readonly NameMatchingStrategy Flexible = new NameMatchingStrategy(PascalCase, PascalCase);
public static readonly NameMatchingStrategy ToCamelCase = new NameMatchingStrategy(CamelCase, Identity);
public static readonly NameMatchingStrategy FromCamelCase = new NameMatchingStrategy(Identity, CamelCase);
public static readonly NameMatchingStrategy Caseless = new NameMatchingStrategy(Identity, Identity, true);

public NameMatchingStrategy(Func<string, string> sourceMemberNameConverter, Func<string, string> destinationMemberNameConverter, bool ignoreCase = false)
{
    SourceMemberNameConverter = sourceMemberNameConverter;
    DestinationMemberNameConverter = destinationMemberNameConverter;
    IgnoreCase = ignoreCase;
}

public NameMatchingStrategy()
{
}

I also added a constructor here to allow the IgnoreCase property to be specified independently of the templates.

In ValueAccessingStrategy.cs, PropertyOrFieldFn, use .Equals() with StringComparison instead of ==:

return members.Where(member => strategy.SourceMemberNameConverter(member.Name).Equals(destinationMemberName,
    strategy.IgnoreCase == true ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))
    .Select(member => member.GetExpression(source))
    .FirstOrDefault();

GetMethodFn and DictionaryFn would also require this.

When setting the NameMatchingStrategy (using GlobalSettings, for example) you can then do something like this:

TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(
    new NameMatchingStrategy(NameMatchingStrategy.Identity, NameMatchingStrategy.Identity, true));
@chaowlert
Copy link
Collaborator

Thanks for the codes, I can add supports for ignore case later.
For now, could you do something like

Func<string, string> toLower = s => s.ToLower();
TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(
    new NameMatchingStrategy {
        SourceMemberNameConverter = toLower,
        DestinationMemberNameConverter = toLower
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants