Как сравнить коллекцию AuthorizationRuleCollection двух разных папок? Я хочу знать, является ли ACL таким же.
Мое решение состояло бы в том, чтобы просмотреть каждый элемент и вычислить хэш IdentityReference.Value + AccessMask. Затем просуммируйте их все и сравните итоги каждой коллекции.
Есть ли лучший подход?





Я бы использовал 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);
Кажется, это работает нормально, даже если порядок внутри коллекций другой:
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;
}
}
Поскольку обе коллекции могут иметь разные порядки, это даст вам ложные результаты.