patterncsharpMinor
Building a string representing 50+ ActiveDirectory options
Viewed 0 times
optionsbuildingactivedirectorystringrepresenting
Problem
I have a switch statement used to handle options that a user selected (stored in an array). The array is iterated through, and for each element (enum object) in the array, an appropriate action is performed. However, the enum has over 50 items, so the switch statement is very long.
The items are all necessary and related, so they cannot be moved or removed. They also each call a method or get a property of an object, so no dictionaries. Are there any other options to make this shorter?
The items are all necessary and related, so they cannot be moved or removed. They also each call a method or get a property of an object, so no dictionaries. Are there any other options to make this shorter?
public string GetUserAttributes(UserPrincipal user,
ActiveDirectoryUserAttribute[] attributes)
{
var userAsDirectoryEntry
= (DirectoryEntry)user.GetUnderlyingObject();
var userAttributes = string.Empty;
foreach (ActiveDirectoryUserAttribute attribute in attributes)
{
switch (attribute)
{
case ActiveDirectoryUserAttribute.AccountExpirationDate:
userAttributes += AttributeToString(
user.AccountExpirationDate.ToString());
break;
case ActiveDirectoryUserAttribute.AccountLockoutTime:
userAttributes += AttributeToString(
user.AccountLockoutTime.ToString());
break;
case ActiveDirectoryUserAttribute.Assistant:
userAttributes += AttributeToString(
userAsDirectoryEntry.Properties[AttributeAssistant]
.Value.ToString());
break;
case ActiveDirectoryUserAttribute.BadLogonCount:
userAttributes += AttributeToString(
user.BadLogonCount.ToString());
break;
...
}
}
return userAttributes;
}Solution
You can put the
You can also use the collection initializer for dictionary to cut down some letters :
Personally I prefer the C# 6 collection initializer the most, second by the method shown in first snippet, and lastly the older initializer.
switch-cases into a dictionary to reduce the boilerplate case and break. The foreach and the string concatenation part can also be reduced with string.Concat(...) or string.Join(delimiter, ...):public string GetUserAttributes(UserPrincipal user, ActiveDirectoryUserAttribute[] attributes)
{
var userAsDirectoryEntry = (DirectoryEntry)user.GetUnderlyingObject();
var getters = new Dictionary>();
getters[ActiveDirectoryUserAttribute.AccountExpirationDate] = () => user.AccountExpirationDate;
getters[ActiveDirectoryUserAttribute.AccountLockoutTime] = () => user.AccountLockoutTime;
getters[ActiveDirectoryUserAttribute.Assistant] = () => userAsDirectoryEntry.Properties[AttributeAssistant].Value;
getters[ActiveDirectoryUserAttribute.BadLogonCount] = () => user.BadLogonCount;
// ...
// just concat them directly, like you are doing now
return string.Concat(attributes.Select(attr => getters[attr]()));
// or, you can separate them with a comma, or anything :
return string.Join(", ", attributes
.Select(attr => getters[attr]()));
}You can also use the collection initializer for dictionary to cut down some letters :
var getters = new Dictionary>
{
// C# 6
[ActiveDirectoryUserAttribute.AccountExpirationDate] = () => user.AccountExpirationDate,
[ActiveDirectoryUserAttribute.AccountLockoutTime] = () => user.AccountLockoutTime,
// older version
{ ActiveDirectoryUserAttribute.Assistant, () => userAsDirectoryEntry.Properties[AttributeAssistant].Value },
{ ActiveDirectoryUserAttribute.BadLogonCount, () => user.BadLogonCount },
// ...
};Personally I prefer the C# 6 collection initializer the most, second by the method shown in first snippet, and lastly the older initializer.
Code Snippets
public string GetUserAttributes(UserPrincipal user, ActiveDirectoryUserAttribute[] attributes)
{
var userAsDirectoryEntry = (DirectoryEntry)user.GetUnderlyingObject();
var getters = new Dictionary<ActiveDirectoryUserAttribute, Func<object>>();
getters[ActiveDirectoryUserAttribute.AccountExpirationDate] = () => user.AccountExpirationDate;
getters[ActiveDirectoryUserAttribute.AccountLockoutTime] = () => user.AccountLockoutTime;
getters[ActiveDirectoryUserAttribute.Assistant] = () => userAsDirectoryEntry.Properties[AttributeAssistant].Value;
getters[ActiveDirectoryUserAttribute.BadLogonCount] = () => user.BadLogonCount;
// ...
// just concat them directly, like you are doing now
return string.Concat(attributes.Select(attr => getters[attr]()));
// or, you can separate them with a comma, or anything :
return string.Join(", ", attributes
.Select(attr => getters[attr]()));
}var getters = new Dictionary<ActiveDirectoryUserAttribute, Func<object>>
{
// C# 6
[ActiveDirectoryUserAttribute.AccountExpirationDate] = () => user.AccountExpirationDate,
[ActiveDirectoryUserAttribute.AccountLockoutTime] = () => user.AccountLockoutTime,
// older version
{ ActiveDirectoryUserAttribute.Assistant, () => userAsDirectoryEntry.Properties[AttributeAssistant].Value },
{ ActiveDirectoryUserAttribute.BadLogonCount, () => user.BadLogonCount },
// ...
};Context
StackExchange Code Review Q#129457, answer score: 4
Revisions (0)
No revisions yet.