Reputation: 444
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. I have the same luck with Arrays + other instances that aren't defined as an interface.
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. 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?
Upvotes: 3
Views: 3768
Reputation: 52240
Use GetType()
to get the type of the concrete instance.
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
Upvotes: 1
Reputation: 6510
John Wu's answer should work if you already have an instance of an object on which you can call GetType. If you just have a type like IList<string>
, or any interface type, you won't find a constructor. 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.
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);
Upvotes: 2