Сравните ACL двух папок - PullRequest
       8

Сравните ACL двух папок

2 голосов
/ 15 марта 2019

Как вы сравниваете AuthorizationRuleCollection двух разных папок? Я хочу знать, совпадает ли ACL.

Мое решение состоит в том, чтобы просмотреть каждый элемент и вычислить хеш IdentityReference.Value + AccessMask. Затем суммируйте их все и сравните итоги каждой коллекции.

Есть ли лучший подход?

Ответы [ 2 ]

2 голосов
/ 15 марта 2019

Я бы использовал SequenceEqual от LINQ, поскольку AuthorizationRuleCollection реализует IEnumerable. Единственная проблема заключается в том, что AuthorizationRule не переопределяет object.Equals(), что означает, что нам нужно предоставить пользовательский IEqualityComparer<AuthorizationRule>, например, так:

public class AuthorizationRuleEqualityComparer : IEqualityComparer<AuthorizationRule>
{
    public static readonly AuthorizationRuleEqualityComparer Instance = new AuthorizationRuleEqualityComparer();

    private AuthorizationRuleEqualityComparer()
    {
    }

    public bool Equals(AuthorizationRule l, AuthorizationRule r)
    {
        // Compare more fields if needed.
        return l.IdentityReference == r.IdentityReference;
    }

    public int GetHashCode(AuthorizationRule rule)
    {
        return rule.IdentityReference.GetHashCode();
    }
}

Использование:

AuthorizationRuleCollection arc1;
AuthorizationRuleCollection arc2;
var equal = arc1
    .OfType<AuthorizationRule>()
    .SequenceEqual(
        arc2.OfType<AuthorizationRule>(),
        AuthorizationRuleEqualityComparer.Instance);
0 голосов
/ 15 марта 2019

Кажется, это работает нормально, даже если порядок внутри коллекций другой:

        internal static bool IsEqual(this AuthorizationRuleCollection authorizationRuleCollectionA, AuthorizationRuleCollection authorizationRuleCollectionB)
    {
        if (authorizationRuleCollectionA.Count != authorizationRuleCollectionB.Count)
        {
            return false;
        }

        int hash1 = CalculateHash(authorizationRuleCollectionA);
        int hash2 = CalculateHash(authorizationRuleCollectionB);

        return hash1 == hash2;
    }

    /// <summary>
    /// Source: https://stackoverflow.com/a/263416/10585750
    /// </summary>
    /// <param name="authorizationRuleCollection"></param>
    private static int CalculateHash(AuthorizationRuleCollection authorizationRuleCollection)
    {
        unchecked
        {
            int hash = 17;
            foreach (FileSystemAccessRule fileSystemAccessRule in authorizationRuleCollection)
            {
                hash += CalculateHash(fileSystemAccessRule);
            }
            return hash;
        }
    }

    private static int CalculateHash(FileSystemAccessRule fileSystemAccessRule)
    {
        unchecked
        {
            int hash = 23 * fileSystemAccessRule.IdentityReference.Value.GetHashCode()
                * fileSystemAccessRule.InheritanceFlags.ToString().GetHashCode()
                * fileSystemAccessRule.IsInherited.ToString().GetHashCode()
                * fileSystemAccessRule.PropagationFlags.ToString().GetHashCode()
                * fileSystemAccessRule.FileSystemRights.ToString().GetHashCode()
                * fileSystemAccessRule.AccessControlType.ToString().GetHashCode();
            return hash;
        }
    }
...