简体   繁体   中英

how I can limit the call to only one time for method "utilities.DecryptStringFromBase64String"

I am getting credential data from one of web service call and while decrypt it, the format is "username:::password". I have other class as well and finally I am creating Data class like below,

 var lstStudents = new List<Student>
        {
            new Student
            {
                Name = "studen1",
                Credentials = new List<Credential> {new Credential {Key = "N1", Cred = "pNn/B3yUB+x2yiC310efoAjb8EkNhH1oD3NYF0v5SNxUKPtOtpxL21saVJGjmYPi" }, new Credential { Key = "N2", Cred = "" }}
            },
            new Student
            {
                Name = "studen2",
                Credentials = new List<Credential> {new Credential {Key = "N1", Cred = "PT7CpnUcG7DIrJTxN8CcqoHAyTbNNST3DzGLpGQUHF6/jyooYKW1puXb/a+WX2M8" }, new Credential { Key = "N2", Cred = "" }}
            },
        };

        var filterList = lstStudents.SelectMany(x => x.Credentials.Select(y => 
                new Data
                {
                    StudentName = x.Name, 
                    CredentialKey = y.Key,
                    UserName = utilities.DecryptStringFromBase64String(y.Cred, key).Before(":::") , 
                    Password = utilities.DecryptStringFromBase64String(y.Cred, key).After(":::")
                }))
            .Where(d => d.CredentialKey == "N1")
            .ToList();

Supporting classes,

public class Data
{
    public string StudentName { get; set; }
    public string CredentialKey { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
}

public class Student
{
    public string Name { get; set; }
    public List<Credential> Credentials { get; set; }
}

public class Credential
{
    public string Key { get; set; }
    public string Cred { get; set; }
}

In above code I am calling method DecryptStringFromBase64String 2 times, I would like to call it only one time and prepare my data class, how to do this? Thanks!

This will be easier if you tweak the query to use the actual LINQ language syntax (rather than the extension methods), as then you can use let :

var filterList = (
    from x in lstStudents
    from y in x.Credentials
    let s = utilities.DecryptStringFromBase64String(y.Cred, key)
    let d = new Data
    {
        StudentName = x.Name,
        CredentialKey = y.Key,
        UserName = s.Before(":::"),
        Password = s.After(":::")
    }
    where d.CredentialKey == "N1"
    select d
).ToList();

or to do the where sooner, to avoid some calculations / allocations:

var filterList = (
    from x in lstStudents
    from y in x.Credentials
    where y.Key == "N1"
    let s = utilities.DecryptStringFromBase64String(y.Cred, key)
    let d = new Data
    {
        StudentName = x.Name,
        CredentialKey = y.Key,
        UserName = s.Before(":::"),
        Password = s.After(":::")
    }
    select d
).ToList();

Personally I'd also change all the x , y , s , d to be more meaningful, but I've left them the same for now, so you can see how it maps.

An alternative would be, as noted by @Sinatr in the comments, to use a lambda with body:

var filterList = lstStudents.SelectMany(x => x.Credentials.Select(y => {
    var s = utilities.DecryptStringFromBase64String(y.Cred, key);
    return new Data {
        StudentName = x.Name, 
        CredentialKey = y.Key,
        UserName = s.Before(":::") , 
        Password = s.After(":::")
    };
}))
.Where(d => d.CredentialKey == "N1")
.ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM