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:
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 theRun()
method on each.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:
Implement a specific version of
Run()
in the class's default interfaceImplement 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?.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
C# Serialized JSON Date to Ruby
Wcf Service Attribute to Log Method Calls and Exceptions
How to Code a Progress Bar for Windows 7 to Also Update Itself on the Taskbar
How to Use HTML.Textboxfor with Input Type=Date
Convert JavaScript Regex to C#
Best Practice: Direct SQL Access VS. Web Service
What Is The Story of Performance Counters for .Net Core
Asp.Net/HTML: HTML Button's Onclick Property Inside ASP.NET (.Cs)
Asp.Net/HTML: HTML Button's Onclick Property Inside ASP.NET (.Cs)
What Is Difference Between Regasm.Exe and Regsvr32? How to Generate a Tlb File Using Regsvr32
Assemblytitle' Attribute in the .Net Framework
Regular Expression to Extract HTML Body Content
How to Get Data by SQLdatareader.Getvalue by Column Name
Does Ef Upsert Have to Be Done Manually
How to Rewrite Complicated Lines of C++ Code (Nested Ternary Operator)