Reputation: 1147
Suppose I have the following interface and implementing class:
public interface IInterface
{
string AMember { get; }
string OtherMember { get; }
}
public class Class : IInterface
{
public string OtherMember { get { return "other"; } }
public string AMember { get { return "class"; }}
string IInterface.AMember { get { return "explicit"; } }
}
Now I get the members via reflection and want to test if they are an interface implementation.
public class Program
{
public static void Main()
{
var inst = new Class();
var members = typeof(Class).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach(var member in members)
{
object val;
try
{
val = member.GetValue(inst);
}
catch(MethodAccessException e)
{
val = "EXPLICIT";
}
Console.Out.WriteLine(string.Format("{0}: {1} is interface implementation? {2}", member.Name, val, false /*member.IsInterfaceImplementation*/));
}
}
}
How can I test if the member is the implementation of an interface?
Upvotes: 1
Views: 1111
Reputation: 1609
In case you really just want to check whether a member of a certain class comes from any interface, you could do the following:
bool myMemberComesFromInterface = typeof(Class).GetInterfaces()
.SelectMany(i => i.GetMember("MyMember")).Any();
There is an edge case though: explicit interface implementation; consider:
public interface IInterface
{
int MyMember { get; }
}
public class Class : IInterface
{
public string MyMember => "foo";
int IInterface.MyMember => 2;
}
The above code would yield true
in this case and I can't be sure if that's what you want in your use case. If you don't want this, I think you'd have to do comparisons of the members you found with the SelectMany(...)
on a per-interface basis. Perhaps InterfaceMapping
(see here) could be of use as well here.
Edit: Since it is now clarified that this case is of interest, I tried fiddling something that would work for your case:
var interfaces = typeof(Class).GetInterfaces()
.ToDictionary(i => i.FullName, i => i.GetProperties().Select(p => p.Name).ToList());
var properties = typeof(Class).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance);
// explicitly implemented properties
foreach (var pi in properties.Where(pi => pi.Name.Contains(".")))
{
Console.WriteLine($"Explicitly implemented property {pi.Name} found.");
var parts = pi.Name.Split('.');
string interfaceName = string.Join(".", parts.Take(parts.Length - 1));
string propertyName = parts[parts.Length - 1];
interfaces[interfaceName].Remove(propertyName);
}
// rest
foreach (var pi in properties.Where(pi => !pi.Name.Contains(".")))
{
// instead of this, you could also use LINQ and SelectMany
// on the Values to check for containment
bool found = false;
foreach (var interfaceName in interfaces.Keys)
{
if (interfaces[interfaceName].Contains(pi.Name))
{
found = true;
Console.WriteLine($"Found property {pi.Name} in interface {interfaceName}.");
}
}
if (!found)
{
Console.WriteLine($"Property {pi.Name} is self-defined.");
}
}
For your example, this give me the following output:
Explicitly implemented property Fiddle.IInterface.AMember found.
Found property OtherMember in interface Fiddle.IInterface.
Property AMember is self-defined.
Upvotes: 3
Reputation: 433
You can use the following code:
var interfaceType = typeof(IInterface);
var interfaceVar = typeof(Class).GetInterface(interfaceType.Name);
var returnMethod = interfaceVar.GetMethods().FirstOrDefault(m
=>m.ReturnType.IsSubclassOf("MyMember") || m.ReturnType == "MyMember");
if(returnMethod != null){
// your member is implementation of interface
}
Upvotes: 0