简体   繁体   English

使用反射时如何找到接口实例的具体类型?

[英]How to find the concrete type of interface instance when using reflection?

I'm currently trying to create an instance of an object that was defined as an interface. 我当前正在尝试创建一个定义为接口的对象的实例。 Specifically: 特别:

public static class A {
    public static IList<string> SampleList { get; set; }

    public void Initialize() { 
        SampleList = new List<string>();
    }
}

// In some other class where I don't have an instance of A.
// This class is in a separate DLL + running in a separate process as A
var propertyInfo = typeof(A).GetProperty("SampleList");
propertyInfo.PropertyType.GetConstructors().Any(); // false
// ^ I would like this to be true

When SampleList is instead typed as a List instead of the interface (IList) I'm able to produce a constructor and instantiate an instance of this list. 当将SampleList而不是接口(IList)键入为List时,我可以生成一个构造函数并实例化此列表的实例。 I have the same luck with Arrays + other instances that aren't defined as an interface. 我对Arrays和其他未定义为接口的实例具有同样的运气。

Something else I noticed is that when I use List, and invoke PropertyType.GetInterfaces() I get a list of 8 interfaces while when I invoke the same command using an IList instance I only get 3 interfaces. 我注意到的另一件事是,当我使用List并调用PropertyType.GetInterfaces()时,我会得到8个接口的列表,而当我使用IList实例调用同一命令时,我只会得到3个接口。 In general I'm getting a lot less information. 一般来说,我得到的信息要少得多。

I was wondering if it was possible to find out the concrete class itself? 我想知道是否有可能找出具体的课程本身? If so, how? 如果是这样,怎么办?

Use GetType() to get the type of the concrete instance. 使用GetType()获取具体实例的类型。

    var propertyInfo = typeof(A).GetProperty("SampleList");
    var propertysTypeHasConstructor = propertyInfo.PropertyType.GetConstructors().Any(); // false
    Console.WriteLine(propertysTypeHasConstructor);

    var concreteInstanceType = A.SampleList.GetType();
    var concreteInstanceHasConstructor = concreteInstanceType.GetConstructors().Any(); // true
    Console.WriteLine(concreteInstanceHasConstructor);

Output: 输出:

False
True

John Wu's answer should work if you already have an instance of an object on which you can call GetType. 如果您已经具有可以调用GetType的对象的实例,则John Wu的答案应该起作用。 If you just have a type like IList<string> , or any interface type, you won't find a constructor. 如果您只有IList<string>类的类型,或者任何接口类型,都将找不到构造函数。 I think the closest you could get would be to search the assemblies in the AppDomain for a type that implements the interface and has a default constructor. 我认为您可以找到的最接近的方法是在AppDomain中搜索程序集,以查找实现该接口并具有默认构造函数的类型。

var interfaceType = typeof(IList<string>);
var ctor = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(a =>
    {
        try
        {
            return a.GetTypes();
        }
        catch
        {
            return new Type[0];
        }
    })
    .Select(t => interfaceType.IsGenericType && t.IsGenericType && interfaceType.GetGenericArguments().Length == t.GetGenericArguments().Length && t.GetGenericArguments().All(a => a.GetGenericParameterConstraints().Length == 0) ? t.MakeGenericType(interfaceType.GetGenericArguments()) : t)
    .Where(interfaceType.IsAssignableFrom)
    .SelectMany(t => t.GetConstructors())
    .FirstOrDefault(c => c.GetParameters().Length == 0);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM