How to reflect the generic parameter that was used for inheritance - c#

Let's say I have the following class hierarchy: TaskViewer inherits from ListViewer<Task> which in turn inherits from ViewerBase.
If I debug into a method that is declared in ViewerBase and look at this.GetType(), it correctly returns TaskViewer. However, I cannot find a property or method which will return me the generic parameter that was used in the inheritance, i.e. Task. Obviously if I was in the context of TaskViewer or ListViewer<T> then I would easily know this.
I can see that it was Task by looking at the BaseType.FullName property, but I've been through the list and nothing I can see identifies itself as having used that generic argument.
How might I get the original generic parameter from within this method in the root class?

You can access the generic argument of the base type as follows (assuming only a single type argument).
typeof(TaskViewer).BaseType.GetGenericArguments()[0]
In ViewerBase you would use
this.GetType().BaseType.GetGenericArguments()[0]
but it seems quite weired to look at the generic type arguments of a derived class in the base class. You cannot know waht the actual type is, hence not if it has generic arguments at all. Could you tell something about your usage scenario?

Make sure you're doing this for a good reason. If you're doing this to put the type returned in an if-statement and do something different depending on the type, this is a use for polymorphism, and possibly a generic constraint, not reflection.

Related

Getting around generic type covariance lack of function input

I am trying to make use of covariant types in order to make generics useful.
I have a generic interface foo that I want to be able to both get and set a property of type T. When declaring the object I don't know what implementing instance I'll be given and so covariance allows for the following declaration
Foo<ibasetype> genericFoo = new implementationOfFoo();
Where implementationOfFoo is
Class implementationOfFoo : Foo<baseTypeA>{}
This works for declaration but it doesn't allow the interface to require an instance of the type baseTypeA as a parameter because covariance only allows returning an instance of the type.
I'm unable to make the interface type invariant as is suggested in other posts because that requires I specifically declare the appropriate class type during object declaration which is not possible as I don't know what instance of implementing class I'll be given.
I am also unable to declare a second type and make that type contravariant as that also triggers a compiler error similar to the invariant case during declaration.
The code that uses this class will handle the appropriate object generation based on reflection prior to passing the object to the implementations various functions so there's no concern of any rule breaking and any exceptions that occur will simply be cleaned up as part of the process of building the code that makes use of the interface.
I assume there's some trick with covariance to get around this shortcoming but I haven't found any guides which discuss this concern. How do I get around this?
Per the responses to my initial question, I would like to be able to build an interface with types of various interfaces I define as the requirements of the main generic interface types. For example
Public interface Foo<typeA> where typeA:iModelA{
typeA prop1{get;set;}
Void doSomething (typeA sameAsProp1)
}
The implementation of the interface must be providing a type which implements iModelA so I simply need to use reflection to determine what the type is and then in my case I use the url provided to construct an instance of that type and pass it to the interface instances ModelA parameter. Then when I need the object I just call the ModelA getter and get from the implementation the iModelA it seems appropriate to provide in that instance.
In my code is declare
Foo fooInstance = getFooInstance(inputs)
For example the page I'm constructing has input fields which on a button click generates a new url which is redirected to. Those same url parameters are then reviewed on the subsequent page load to construct an instance of the base object (which is also based on parameters in the url). The setter logic then reloads the fields based on the passed instance of the iModelA objects parameters.
This logic will be the same regardless of the implementation of the interface so I know its a perfect candidate for an interface and the generic types allow me to impose structure across various objects within the implementation. This if two objects need to reference the exact same type, the generic requirements can manage those needs.
I know that I could get away with not doing a generic interface like so
Interface nonGenericFoo{
iModelA prop1{get;set;}
Void doSomething (iModelA sameAsProp1)
}
However, this means that across functions and properties within the main interface the implementation of the interfaces might be declared differently which will be problematic. In addition, the implementing class will need to make assumptions about the implemention instance which I want to avoid. I want all assumptions to be handled by the main code and let the interface implementations know exactly what they're working with.

Changing type using the "string" name [duplicate]

I have an existing base type and I would like to cast it to a derived type base upon the name of the type as a string, so something like this:
public void DoStuffInDerivedType(string derivedName) {
(base as Type.GetType(derivedName)).DoThisThing();
}
I'm pretty sure this can't be done but would be good to know for sure. Thanks
EDIT: I understand that I could construct the object using reflection from the type name but I want use an existing object. And also I know this is generally a bad idea. However I wanted to use this for a SpecFlow BDD Feature.
I'll repeat the advice that you probably don't need to do this, but because I have done this operation before:
Convert.ChangeType(ItemToCast, Type.GetType(stringNameOfType)))
Should work for you.
I don't think you need to cast it to the derived type. You should be able to cast it to the base type and use the shared interface (be it a base class or literal Interface) to perform whatever you want done.
If not, consider adding the behavior as an interface requirement so you can do it that way.
Finally: the one possibility where you'd need to do it this way is if you're overriding the casts...in which case I'm almost certain you can't do this without some heavy duty reflection.

Generic type constraints on an interface method

I'm doing the following in my interface, reason being I don't want to be tightly coupled to the implementation of IEquipment in my implementations of IEquipmentDataProvider
public interface IEquipmentDataProvider
{
IEquipment GetEquipment<E>(string Path) where E : IEquipment, new();
}
But I think that the type constraints should be left to the implementation and I should just declare IEquipment GetEquipment(string path); in my interface. However, if I do that it's an interface for a redundant method as that method will never get called.
Is it considered okay to implement type constraints in an interface method, or is there another pattern I should consider?
Edit:
The reason I'm doing this is because I don't want my data access layer to have to use a concrete implementation of IEquipment and I can leave that to the domain logic layer. Hence the use of the generics , which will be an instance of IEquipment but decided upon by dll. And called with
Equipment eq = da.GetEquipment<Equipment>("somepath"); // where eq is Iequipment, and da is IEquipmentDataProvider
But I think that the type constraints should be left to the implementation and I should just declare IEquipment GetEquipment(string path); in my interface.
While I can see what you mean, I do think it's relevant here. Ignoring your type constraints, your interface definition makes it painfully clear that this is intended to work with equipment:
IEquipmentDataProvider
GetEquipment()
Return type IEquipment
It's almost unavoidable that you'd want to limit the usable types to those that implement IEquipment.
Does the following make sense to you? Is this an intended use case?
public class StringProvider : IEquipmentDataProvider
{
//...
}
var provider = new StringProvider();
var equipment = provider.GetEquipment<string>(myPath);
I'm pretty sure that it doesn't. Because it doesn't make sense to use anything other than an IEquipment implementation.
I think the issue is bigger than you're currently discussing. I see some other minor inconsistencies:
You make a generic E type argument, yet your return value is of type IEquipment. Why? Why not make E the return type? Existing code such as IEquipment myEquipment = myProvider.GetEquipment() will still work without needing changes, and you have the optional benefit of returning a specific type should you ever need it.
I don't quite understand why the method is generic but the class/interface itself isn't. There are use cases for generic methods, but yours seems to fit a generic class/interface much better.
I want to further address the second bullet point. Your interface, when implemented, will ensure that every implementation can get every type of `IEquipment.
Compare this to the generic class version:
public interface IEquipmentDataProvider<E> where E : IEquipment, new()
{
E GetEquipment<E>(string Path);
}
Pretty much the same code. But now, you can implement these interfaces specifically or generically, however you want it:
public class HammerDataProvider : IEquipmentDataProvider<Hammer> {}
public class SawDataProvider : IEquipmentDataProvider<Saw> {}
public class AllEquipmentDataProvider : IEquipmentDataProvider<IEquipment> {}
Every implementation of IEquipmentDataProvider can choose to either limit itself to a specific type (Hammer, Saw), or it can handle every implementation of IEquipment.
Edit
This also allows you to combine multiple interfaces, which can be implemented separately in the same class:
public class HammerAndSawDataProvider : IEquipmentDataProvider<Hammer>, IEquipmentDataProvider<Saw> {}
Due to a lack of type distinction between the two interface methods, you'll need to rely on explicit interface implementation. Maybe not what you want.
If your interface method had had different signatures between different generic types (e.g. GetEquipment<E>(E myEquipment) ), then you could've avoided needing to use explicit interface implementation.
This may be one step too far for your requirements, but it does showcase that you get absolute control over which equipment can be handled by a specific provider.
To summarize
The type constraint seems to be a given, based on the naming that you've used for the class and method.
It would make little to no sense to ever use a type that deviates from the suggested type constraint.
If you're already using a generic type; you're better off having your return type be the generic type. At worst, it doesn't break anything. At best, it allows for better type safety and less hard casting (e.g. it removes the need for performing a cast in Hammer myHammer = (Hammer)provider.GetEquipment(myPath);).
More often than not, you'll want to use the generic parameter at the class/interface level. The main drawback of generic methods (without a generic class) is that you have to repeatedly define a type constraint for every submethod that is called in the toplevel method. Generic methods (without a generic class) are generally only really warranted in "toolkit" methods, as far as I can think of right now.
Pedantic: I would rename the generic parameter to TEquipment (or TE if you want to be terse). Type parameters are usually named in a way that e.g. TElement is read as "type of the Element". But this is a matter of style and naming convention.
In your code, you do adhere to the "interface names begin with I" convention. Generic types have a similar convention about beginning with T.
Response to OP's update
Edit: The reason I'm doing this is because I don't want my data access layer to have to use a concrete implementation of IEquipment and I can leave that to the domain logic layer. Hence the use of the generics , which will be an instance of IEquipment but decided upon by dll.
This somewhat reaffirms my assertion that you should use a generic class/interface, not just a generic method.
If one were to paraphrase this line of code,
IEquipment GetEquipment<E>(string Path) where E : IEquipment, new();
it would become "a GetEquipment generic method with a constraint of type IEquipment with an implementation that has a default constructor".
Instead, the design could simply be an explicit interface method
Equipment eInstance=new Equipment();
IEquipmentDataProvider iEInstance=(IEquipmentIEquipmentDataProvider )eInstance;
iEInstance=iEInstance.GetEquipment(path);
so that, even if you have another class implementing the GetEquipment method differently, you could simply call the right GetEquipment method of IEquipment by using the explicit interface method.
Edit: after the OP's edit
EquipmentDataProvider edp=new EquipmentDataProvider();
IEquipmentDataProvider da=(IEquipmentDataProvider)edp; // An explicit method invocation to ensure that the EquipmentataProvider's GetEquipment and not some other Equipment class' GetEquipment is called. This is what is the intent of the
Equipment eq = da.GetEquipment<Equipment>("somepath");

Does a parameterized return type require a generic method signature?

Specifically, I'm working with EmguCV's Image type.
I've defined an interface ITransformation with a method ApplyFrom that takes an Image and returns an Image:
public interface ITransformation
{
Image<TColor, TDepth> ApplyFrom<TColor, TDepth>(Image<TColor, TDepth> sourceImage);
}
But this seems awfully verbose with type parameters, especially when that method gets used. Ideally, the interface would look like this:
public interface ITransformation
{
Image ApplyFrom(Image sourceImage);
}
But Visual Studio complains about Image requiring 2 type parameters. I don't want to bind the ApplyFrom() method to a specific color or depth
Do I need to use the generic, verbose first version above?
Or am I missing some possible middle ground between the two versions?
Do I need to use the generic, verbose first version above?
Yes - you need to specify generic parameters when referring to a generic type. Just like you can't reference List as a type - you need to fully qualify the generic parameter (List<T>, List<int>, etc.)
The compiler may be able to infer generic parameters when using the method, but the declaration must include the generic parameters in all three positions that you have them.
About the only thing you can do to reduce the verbosity (and still keep the function generic) is to shorten the generic parameter names:
public interface ITransformation
{
Image<C, D> ApplyFrom<C, D>(Image<C, D> sourceImage);
}
You lose the self-documenting nature of the generic parameters, but to the compiler there is no difference.
I don't want to bind the ApplyFrom() method to a specific color or depth
That's exactly what generics are for. It's for writing a method that doesn't require those types that are generic to be specified when writing this method.
Those are your choices; specify the exact types used by the images, without allowing them to ever be anything else, or make the method generic, so that the caller can provide an image with any types that it wants as the generic arguments.
You can make the method shorter, but at the cost of making the interface generic (and thus more verbose).
public interface ITransformation<T, TColor, TDepth> where T : Image<TColor, TDepth> {
T ApplyFrom(T sourceImage);
}

terminology for what a class does with generic type parameter

Given class MyClass<T> what is the proper terminology to describe what MyClass does with the generic type parameter?
Implements? Uses? These don't sound right. I've skimmed through MS documentation on generics and they seem to talk around it without using a term.
My question came to mind when writing a comment about code that inspected the type of generic type parameter to see if it was assignable from a particular base type. I was planning to say something like: "check to see if the generic class verbs the specified type". I can word it differently, but wanted to know if there was a good verb to use.
The T parameter is part of the type, so you should just say MyClass of T. It "does" nothing with T.
From simple view, you could say that generic function accepts a generic type parameter.
You could specialize this to contains, but if you want to be fancy, you might say, a generic type reifies a type parameter.
From the Wikipedia article:
"In C#, reification is used to make parametric polymorphism
implemented as generics as a first-class feature of the language"
The definition on Dictionary.com
re·i·fy/ˈriəˌfaɪ, ˈreɪ-/
verb (used with object), re·i·fied, re·i·fy·ing.
to convert into or regard as a concrete thing: to reify a concept.
The way it's used in the MSDN documentation is MyClass of T.
It does not do anything with T. T is its parameter.
void doNothing(int i)
{
}
What does this do with i? Nothing. i is its parameter.
The system binds an open-generic type MyClass<> to a particular type (e.g. Int32) to yield a closed generic type MyClass<Int32>. The former class is effectively used only as a template for the system to produce the latter; the latter has the type built into it. Note that the generation of the closed-form generic from the open-form generic is done by the system, and not by the class itself. A class can include constraints on its generic parameters, but otherwise has no control or involvement in the process.
Type parameterization is what I would call it. Also type specification deferment.
Since List<int> is a "List of int", probably the 'verb' you're looking for is "the generic class is of the specified type"

Categories