Finding the Concrete Type Behind an Interface Instance

Finding the Concrete Type behind an Interface instance

Type objectType = myObject.GetType();

Should still give you the concrete type, according to your example.

How to find the concrete type of interface instance when using reflection?

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

C# Property that returns interface type when accessed through an interface, and concrete type when accessed through concrete class

You need to add explicit interface implementation in CA.

public CA: IA
{
public CB B { get; }
IB IA.B { get => B; }
}

Get concrete class of interface field using Java reflection

getDeclaredFields() (or any other method of java.lang.Class for that matter) returns the compile-time data that's available for the class - it cannot return data based on a specific instance you're using.

What you could do is simply retrieve the instance you're holding and query its type:

System.out.println(a.property.getClass());

EDIT:

To address the comments, this can also be done by reflection, but would still have to address a specific instance:

for (Field f : a.getClass().getDeclaredFields()) {
Class<?> cls = f.get(a).getClass();
System.out.println
(f.getName() + " is set with a concrete class of " + cls.getName());
}

If method returns interface type, why can't I pass the result to a concrete type?

Well, for starters, just look at the members of IList and compare it with List. List has methods that an IList doesn't. (List has a BinarySearch method that IList doesn't, just as a single example.)

Arrays also implement IList, as an example. An array however is not a List, so you can't, and shouldn't, be able to pass a string[] to a method that accepts a List<string>.

You have a few possible solutions. One would be to just change your method to return a List<string> rather than an IList<string> (that's what I'd suggest). If that's what you really need then you shouldn't be restricting the return type to IList<string>. Another (poorer) option would be to cast the result back to a List<string> before passing it to the next method, since you happen to know that it's what the underlying type really is.

Why can't I use a compatible concrete type when implementing an interface

This is a Type Covariance/Contravariance issue (see http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#C.23 ).

There's a workaround: use explicit interfaces, like so:

public class Bar : IFoo {

private IList<int> _integers;

IEnumerable<int> IFoo.integers {
get { return _integers };
set { _integers = value as IList<int>; }
}

public IList<int> integers {
get { return _integers; }
set { _integers = vale; }
}
}

Note that integers should be TitleCased to conform to .NET's guidelines.

Hopefully you can see the problem in the code above: IList<int> is compatible with IEnumerable<int> only for the accessor, but not for setting. What happens if someone calls IFoo.integers = new Qux<int>() (where Qux : IEnumerable<int> but not Qux : IList<int>).

How to get registered service by its concrete type instead of its interface type?

Try registering type directly like so

public void ConfigureServices(IServiceCollection services)
{
// container will create the instance of this type
services.AddScoped<ConcreteRepository>();
}

Then you will be able to resolve type directly with

var concreteRepositoryInstance =  
httpContext.RequestServices.GetService(typeof(ConcreteRepository))
as IEntityOwner;

Force parameter of interface method to be a concrete type per class implementation

Use two prototypes

My suggestion is to use two method prototypes for Run(), exposing a different prototype depending on what the caller is doing. This way you can offer both a type-safe and generic version of Run().

Explanation

The problem is you have two conflicting requirements:

  1. You want to be able to treat all vehicles the same, i.e. store them in a List<Vehicle> and be able to iterate through them and call the Run() method on each.

  2. You want each vehicle type to only allow certain types of parameters, i.e. you want different compile-time rules for each type of vehicle. Thus you actually do not want to be able to iterate through them and run Run() on each identically; in fact you specifically want a compile time error.

This sound very contradictory, but there is some magic you can do to make something somewhat sensible and reasonably safe.

Solution details

The solution I would suggest is to implement Run() twice:

  1. Implement a specific version of Run() in the class's default interface

  2. Implement a generic version of Run() explicitly in the Vehicle interface. If you don't know what this means, see this question: What's the difference between implementing an Interface explicitly or implicitly?.

  3. Call the former from the latter, filtering the input as needed (e.g. using OfType()).

For example:

class AirPlane : Vehicle
{
IEnumerable<BaseOutput> Vehicle.Run(IEnumerable<BaseParam> parameters, object anotherVal)
{
return Run(parameters.OfType<AirPlaneParam>(), anotherVal);
}
public IEnumerable<BaseOutput> Run(IEnumerable<AirPlaneParam> parameters, object anotherVal)
{
//Your implementation
}
}

Now you can have your cake and eat it too:

var baseParameters = new List<BaseParam>();
var airPlaneParameters = new List<AirPlaneParam>();
var vehicles = new List<Vehicle>();

foreach (Vehicle vehicle in vehicles)
{
vehicle.Run(baseParameters, "Foo"); //Works, although only airplane parameters will get processed
vehicle.Run(airPlaneParameters, "Foo"); //Works, due to generic covariance
}

foreach (AirPlane airplane in vehicles.OfType<AirPlane>())
{
airplane.Run(baseParameters, "Foo"); //Does not compile
airplane.Run(airPlaneParameters, "Foo"); //Works
}

And here is a link to the working code on DotNetFiddle.

Getting all types that implement an interface

Mine would be this in c# 3.0 :)

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));

Basically, the least amount of iterations will always be:

loop assemblies  
loop types
see if implemented.


Related Topics



Leave a reply



Submit