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

时间:2018-01-05 00:27:08

标签: c# reflection

我目前正在尝试创建一个定义为接口的对象实例。具体做法是:

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

当SampleList被替换为List而不是接口(IList)时,我能够生成一个构造函数并实例化该列表的实例。我对Arrays +未定义为接口的其他实例也有同样的好运。

我注意到的其他事情是,当我使用List,并调用PropertyType.GetInterfaces()时,我得到了8个接口的列表,而当我使用IList实例调用相同的命令时,我只获得3个接口。总的来说,我收到的信息要少得多。

我想知道是否有可能找到具体的课程本身?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:1)

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

输出:

False
True

答案 1 :(得分:0)

如果您已经有一个可以调用GetType的对象实例,那么John Wu的答案应该有效。如果您只有IList<string>类型或任何接口类型,则不会找到构造函数。我认为你能得到的最接近的是在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);