I'm working on a C# console application. My objective is to create an object called GroupEntity, preferably of non generic type.
Inside this GroupEntity object will be a List of 'AttributeFilter' object which contains object of Generic type which hold the attribute name on a user object in Active Directory and the possible values of those user objects. The reason I want the AttributeFilter object to take a generic type is because some attributes on user objects in AD are string, some are int32, some are int64 etc.
Here are my classes (I've cut out the contructorse etc to save space here)
public class AttributeFilter<T> : IEqualityComparer<AttributeFilter<T>>
{
private string _attributeName;
private T _attributeValue;
private List<T> _attributeValues { get; set; }
public AttributeFilter(string attributeName)
{
AttributeName = attributeName;
_attributeValues = new List<T>();
}
public void AddValues(T attributeValue)
{
AttributeValue = attributeValue;
if (!_attributeValues.Contains(AttributeValue))
{
_attributeValues.Add(AttributeValue);
}
}
// Ive cut out the getter setter etc that is not relevant
}
Here is the GroupEntity class. Notice I have a
List<AttributeFilter<T>>
field. Problem is I dont know what that T will be until I run program.cs
public class GroupEntity<T>
{
private string _groupName;
// because I want to a have a List<AttributeFilter<T>>, but I dont really want this here. because of program.cs when I initialise a new GroupEntity<> I have to tell it what type. I wont know. The type could be int32, string, long or whatever.
private List<AttributeFilter<T>> _filters;
public void AddFilters(AttributeFilter<T> attributeFilter)
{
if (!_filters.Contains(attributeFilter, attributeFilter))
{
_filters.Add(attributeFilter);
}
}
public GroupEntity()
{
_filters = new List<AttributeFilter<T>>();
}
public GroupEntity(string groupName) : this()
{
_groupName = groupName;
}
}
Now I use program.cs to initialise and test...
class Program
{
static void Main(string[] args)
{
// Create AttributeFilter object for user attribute: EYAccountType
var at1 = new AttributeFilter<string>("EYAccountType");
at1.AddValues("02");
at1.AddValues("03");
at1.AddValues("04");
at1.AddValues("05");
// try adding anothr AtributeFilter with same name.
var at3 = new AttributeFilter<string>("EYAccountType1");
at3.AddValues("06");
at3.AddValues("07");
// Create AttributeFilter object for user attribute: userAccountControl
var at2 = new AttributeFilter<int>("userAccountControl");
at2.AddValues(512);
at2.AddValues(544);
at2.AddValues(546);
at2.AddValues(4096);
// Now create a GroupEntity object
var group1 = new GroupEntity<string>("My_First_AD_Group_Name");
// Try adding the above two AttributeFilter objects we created to the GroupEntity object.
group1.AddFilters(at1);
group1.AddFilters(at3);
// This is the problem. I know why this is happening. because I initialised the var group1 = new GroupEntity<string>. So it wont accept at2 because at2 is taking in int.
//group1.AddFilters(at2);
}
So how can I write my GroupEntity class without a generic parameter so I can hold various types of AttributeFilter<T>
inside it. So for example, I can hold AttributeFilter<int>
and AttributeFilter<string>
and AttributeFilter<long>
I can't seem to figure out this problem.
More or less you can't.
Generic types instantiated with different types has no relationship to each other (i.e. AttributeFilter<long>
and AttributeFilter<int>
don't get any common base class - they are as differnet as Exception
and HttpClient
). So there is no way to put instances of such types into single collection with strong typing.
Standard solution - use non-generic base class or interface for your AttributeFilter<T>
type. Alternatively - store them as collection of object
and lose all type safety, or maybe collection dynamic
which at least give you chance to call methods (at cost of reflection).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With