1

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);
AnKing
  • 1,994
  • 6
  • 31
  • 54
  • Does this answer your question? [Setting generic type at runtime](https://stackoverflow.com/questions/2604743/setting-generic-type-at-runtime) `MakeGenericType` is what you are looking for – Charlieface Jan 02 '22 at 01:39

2 Answers2

2

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; }
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • can you give an example of how i can use the new type to cast an instance to it? (I edited the question to give a sample of what i need) – AnKing Jan 02 '22 at 01:50
  • @AnKing - You can't cast it as you're dealing with types at run-time and casting only works when you know the types at compile-time. The only thing you can do is call a method using reflection that then brings the code back to being compile-time safe. – Enigmativity Jan 02 '22 at 01:52
  • can you elaborate on "call a method using reflection that then brings the code back to being compile-time safe"? How can i do so? when i create an instance using `Activator.CreateInstance(prop.PropertyType)` it just returns me an `object` – AnKing Jan 02 '22 at 01:57
  • @AnKing - There you go. – Enigmativity Jan 02 '22 at 02:00
  • Awesome! I must be really slow but I cannot figure out what `this` refers to in the latest update – AnKing Jan 02 '22 at 02:13
  • @AnKing - Sorry, `this` class that contains `SomeMethod`. You can replace it with an instance of a class that contains the method. – Enigmativity Jan 02 '22 at 02:26
  • For some reason when i create a `WorkOrderStatus` using Activator it comes back with instance that doesnt implement `SomeMethod` so that `instance.GetType().GetMethod("SomeMethod"....` returns null – AnKing Jan 02 '22 at 02:44
  • @AnKing - I didn't expect `WorkOrderStatus` to contain the method. How have you got it defined? – Enigmativity Jan 02 '22 at 04:04
  • @AnKing - Did you run my code without any changes and see it work? – Enigmativity Jan 02 '22 at 04:05
0

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<>)));
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • what if it implements ICustomEnum and not the "WorkOrderStatus"? the type "WorkOrder" is not known at runtime and also derived thru reflection. Also this doesnt help me to create an instance of this class thru Activator and cast it to the proper interface – AnKing Jan 02 '22 at 01:18
  • Do you need property which implements the generic interface `ICustomEnum<>` or a specific version of it ? – Anu Viswan Jan 02 '22 at 01:21
  • I edited the question to give more context – AnKing Jan 02 '22 at 01:26