在C#中将一个泛型类封装在非泛型类中

5
我正在开发一个C#控制台应用程序。我的目标是创建一个名为GroupEntity的对象,最好是非泛型类型。
在这个GroupEntity对象内部,将包含一个'AttributeFilter'对象列表,其中包含泛型类型的对象,该对象在Active Directory中保存用户对象上的属性名称和这些用户对象的可能值。我希望AttributeFilter对象采用泛型类型,因为AD中用户对象的某些属性是字符串,有些是int32,有些是int64等。
以下是我的类(我已经删除了构造函数等内容以节省空间)
    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
}

这里是GroupEntity类。请注意,我有一个

标签。
List<AttributeFilter<T>>

字段。问题是在运行program.cs之前我不知道那个T将会是什么。

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;
    }

}

现在我使用program.cs进行初始化和测试...

    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);

}

那么我该如何编写我的GroupEntity类,而不需要泛型参数,以便可以将各种类型的AttributeFilter<T>存储在其中。例如,我可以存储AttributeFilter<int>AttributeFilter<string>AttributeFilter<long>

我似乎无法解决这个问题。


2
创建一个非泛型的AttributeFilter基类,它有一个泛型派生类AttributeFilter<T>,并在GroupEntity中引用这个基类。 - Michael Liu
在您的系统中,“GroupEntity”对象的实际用例是什么?拥有三个字段(List<AttributeFilter<int>>List<AttributeFilter<long>>List<AttributeFilter<string>>)是否可以成为解决方案?否则,如果您在编译时不知道类型参数,则泛型很可能不是正确的选择。 - Zdeněk Jelínek
这只是三个例子。基本上,我正在尝试为在AD用户属性中使用的任何数据类型创建AttributeFilter<T>。字符串、长整型和int32是常见的。但我还看到了字符串数组、字节数组、日期时间等等。所以我将不得不创建所有这些。 - user5078178
1个回答

3

基本上是不可能的。

使用不同类型实例化的泛型之间没有关系(即AttributeFilter<long>AttributeFilter<int>没有任何共同的基类 - 它们与ExceptionHttpClient一样不同)。因此,无法将这些类型的实例放入具有强类型的单个集合中。

标准解决方案-为你的AttributeFilter<T>类型使用非泛型基类或接口。或者 - 将它们存储为object的集合并失去所有类型安全性,或者可以使用带有dynamic的集合,以便可以调用方法(但需要使用反射)。


感谢Alixei Lenenkov和Michael Liu提供的建议。 - user5078178

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接