声明类引用的列表

时间:2018-05-28 00:10:15

标签: c# reflection collections

我需要声明一个类引用列表。具体来说,是一个实现接口的类列表,我在这里称之为IInterface

类似于List如何成为类型列表,如下所示:

List<Type> types = new List<Type> {string, bool, int, float};

我需要完成同样的事情,其中​​每个都是我自己的类并实现接口IInterface所以:

List<(idk)> references = new List<(idk)> {myClass, myClass2, myClass3};

并且所有这些都是MyClass : IInterfaceMyClass2 : IInterfaceMyClass3 : IInterface

我需要这个,这样当我创建类型的实例时,编译器就会知道该类型实现了IInterface

3 个答案:

答案 0 :(得分:2)

如果您基本上需要List<Type>,其中Type是实现接口所需的,并且您希望在编译时强制执行此操作,实际上可以通过包装List<Type>和使add方法具有约束泛型类型参数并使用它来添加到列表中,但使用它可能有点笨拙(您将无法使用您在问题中提到的nice collection initializer语法):

public class TypeList<T> : IEnumerable<Type>
{
    private List<Type> _list = new List<Type>();

    public void Add<TAdd>() where TAdd : T
    {
        _list.Add(typeof(TAdd));
    }

    public IEnumerator<Type> GetEnumerator() => _list.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
}

此类的泛型类型参数是您希望列表约束的类型,因此在您的示例中,使用列表将如下所示:

var list = new TypeList<IInterface>();
list.Add<MyClass>();
list.Add<MyClass2>();
list.Add<MyClass3>();

这些将无法编译:

list.Add<string>();
list.Add<bool>();
list.Add<int>();
list.Add<float>();

答案 1 :(得分:1)

您只需List<Type>此后TypeOf(myClass), TypeOf(myClass2)...作为值。如果要实际验证这些类型是否实现IInterface,则必须进行额外检查。您无法在编译时指定类型应该只是实现您的接口的类型。

除此之外,这听起来像是依赖注入的先决条件,如果是这样的话,你可能想要采用Microsofts Unity依赖注入框架。

答案 2 :(得分:0)

  

我需要这个,这样当我创建类型的实例时,编译器就会知道该类型实现了IInterface。

下面我将向您展示两种可能的方法来获取正在实施type的那些类的IInterface列表。因此,在创建新对象时,您可以使用此列表来确定此类是否正在实现IInterfce

  • 编译时间解决方案

如果你想要一个编译时解决方案,你应该有一个List<IInterface>,那么在这个实现IInterface的列表中只允许那些类的对象。拥有此列表(只有那些实现IInterface的类的对象后,使用此列表来准备类型列表。

对于Ex。

班级Demo实现IInterfaceDemo2则不会。

    List<IInterface> listOfIInterface = new List<IInterface>();
    listOfIInterface.Add(new Demo());
    listOfIInterface.Add(new Demo2()); //this line will have compile time error

现在使用此列表准备类型列表

    List<Type> listOfIInterfaceType = new List<Type>();
    foreach(object obj in listOfIInterface)
    {
        listOfIInterfaceType.Add(obj.GetType());
    }
  • 运行时解决方案

如果您想为问题提供更多动态和运行时解决方案,请尝试此操作。

如果有多个类,并且您想知道哪个类实现IInterface并将这些类的类型选择到列表中。你可以尝试下面的代码。

假设有两个类DemoDemo2Demo确实实现了IInterfaceDemo2没有实现。

如果您拥有这两个类的对象,则将它们放入Object列表并在此列表中循环并执行以下逻辑。

    List<object> listOfObject = new List<object>();
    listOfObject.Add(new Demo()); //Demo Implements IInterface
    listOfObject.Add(new Demo2());//Demo2 doesn't Implement IInterface

    //this will have all possible types
    List<Type> listOfAllType = new List<Type>();
    //this will have type of those class, which implement interface
    List<Type> listOfInterfaceType = new List<Type>();
    //this will have objet of those class, which implement interface.
    List<object> listOfInterfaceObject = new List<object>();

    foreach (object obj in listOfObject)
    {
        Type type = obj.GetType();
        if (!listOfAllType.Contains(type))
            listOfAllType.Add(obj.GetType());

        IInterface testInstance = obj as IInterface;
        if (testInstance != null)
        {
            if (!listOfInterfaceType.Contains(type))
                listOfInterfaceType.Add(type);
            if (!listOfInterfaceObject.Contains(obj))
                listOfInterfaceObject.Add(obj);
        }
    }

请注意,如果任何类没有实现接口,则它的对象不能转换为Interface。因此,如果testInstance在尝试强制转换后仍然为null,那么它的类没有实现接口。