Home > front end >  Find out if class implements an interface thru reflection
Find out if class implements an interface thru reflection

Time:01-02

I have the following class in c#:

public class WorkOrderStatus : ICustomEnum<WorkOrderStatus>
{
}

during runtime I need to figure out if a property of the following class implements the custom interface.

public class WorkOrder{
    public WorkOrderStatus Status {get;set;}
}

So I tried to do the following(using reflection to figure it out):

prop.PropertyType.GetInterfaces().Contains(typeof(ICustomEnum));

But this says that ICustomEnum requires a generic type. So i Tried to do the following, but it doesnt work:

var type = prop.GetType(); 
prop.PropertyType.GetInterfaces().Contains(typeof(ICustomEnum<typeof(type)>));

saying type is a variable but used like a type

[Edit 1]

I later need to be able to create an instance of WorkOrderStatus or any other class that implements this interface thru reflection like this:

var instance = (ICustomEnum<WorkOrderStatus|SomeOtherStatus...>)Activator.CreateInstance(prop.PropertyType);

CodePudding user response:

It's quite simple to do with IsAssignableTo:

Type propertyType = typeof(WorkOrder).GetProperty("Status").PropertyType;
Type interfaceType = typeof(ICustomEnum<>).MakeGenericType(propertyType);
bool implements = propertyType.IsAssignableTo(interfaceType);

And, you might find that typeof(ICustomEnum<>).MakeGenericType(propertyType); solves your problem in your code directly.

So instead of typeof(ICustomEnum<typeof(type)>) you write typeof(ICustomEnum<>).MakeGenericType(type).


Here's how you would use reflection to call a method so that you can move from run-time types back to compile-time types.

void Main()
{
    Type propertyType = typeof(WorkOrder).GetProperty("Status").PropertyType;
    Type interfaceType = typeof(ICustomEnum<>).MakeGenericType(propertyType);
    bool implements = propertyType.IsAssignableTo(interfaceType);
    if (implements)
    {
        object propertyInstance = Activator.CreateInstance(propertyType);
        var method =
            this
                .GetType()
                .GetMethod("SomeMethod", BindingFlags.Instance | BindingFlags.NonPublic)
                .MakeGenericMethod(propertyType);
        method.Invoke(this, new[] { propertyInstance });
    }
}

private void SomeMethod<T>(ICustomEnum<T> customEnum)
{
    Console.WriteLine($"Success with {typeof(T)}");
}

That outputs the following:

Success with WorkOrderStatus

Here's the sundry code you need to run the above:

public class WorkOrderStatus : ICustomEnum<WorkOrderStatus> { }
public interface ICustomEnum<T> { }
public class WorkOrder
{
    public WorkOrderStatus Status { get; set; }
}

CodePudding user response:

You could use GetGenericTypeDefinition for this purpose. For example,

propertyInfo.PropertyType
           .GetInterfaces()
           .Where(x => x.IsGenericType)
           .Any(i => i.GetGenericTypeDefinition() == typeof(ICustomEnum<>));

To retrieve all properties of the Type which implements the particular generic interface, you could

var properties = typeof(WorkOrder).GetProperties();
var result = properties.Where(property=>property.PropertyType
                                               .GetInterfaces()
                                               .Where(x => x.IsGenericType)
                                               .Any(i => i.GetGenericTypeDefinition() == typeof(ICustomEnum<>)));

CodePudding user response:

you can try this

bool implements = typeof(WorkOrder).GetProperties()
.Any(p => p.PropertyType.GetInterfaces().Any(pt => pt.Name  ==typeof(ICustomEnum<>).Name));

or generic variant

var contains=ContainsInterface<WorkOrder,ICustomEnum<WorkOrder>>();

public static bool ContainsInterface<T1,T2>()
{
return  typeof(T1).GetProperties().Any(p => p.PropertyType.GetInterfaces()
    .Any(pt => pt.Name  ==typeof(T2).Name));
}

or list of properties

printProperties<WorkOrder,ICustomEnum<WorkOrder>>();

public static void printProperties<T1,T2>()
{
    foreach (var property in typeof(T1).GetProperties())
    {   
    var contains= property.PropertyType.GetInterfaces()
.Any(pt => pt.Name  ==typeof(T2).Name);
    
     if(contains)Console.WriteLine("Property "  property.Name   " contains interface " typeof(T2).Name);
    }
}
  • Related