Check if a class implements a exact generic class definition - c#

So what I'm trying is to make a method that selects types that implement a generic class, with specific generic value that is only known at run-time.
I have tried something like this
public bool HasCommand(ITerminal owner)
{
var genericType = typeof(Command<>).MakeGenericType(owner.GetType());
var command = typeof(HelloCommand);
return command.GetInterfaces().Any(x => x.GetGenericTypeDefinition() == genericType
&& x.IsGeneric);
}
And hello command looks like this
public class HelloCommand : Command<HallTerminal>
But it always returns false.
Any solutions on what to change / do.
EDIT :
The command class looks like this
public class Command<T>

You can check whether the class is compatible with a given type using is operator:
public bool HasCommand(Terminal owner)
{
var gType = typeof(Command<>).MakeGenericType(owner.GetType());
var bType = typeof(HelloCommand);
if (owner is Command<HallTerminal>)
{
}
}
An example:
public class Person<T>
{
public int Id { get; set; }
}
public class Student : Person<Greeting>
{ }
public class StudentWarmGreeting : Person<WarmGreeting>
{ }
public class Greeting
{
public void SayHello()
{
Console.WriteLine("Hello, it is Greeting!:)");
}
}
public class WarmGreeting
{
public void SayHello()
{
Console.WriteLine("Hello, it is WarmGreeting!:)");
}
}
And you can check using is operator:
static void Main(string[] args)
{
if (studentGreeting is Person<Greeting>)
Console.WriteLine("person is Greeting");
if (studentWarmGreeting is Person<WarmGreeting>)
Console.WriteLine("person is WarmGreeting");
// Visual Studio is clever and it will say:
// "The given expression is never of the provided ('Program.Person') type"
if (studentWarmGreeting is Person<Greeting>)
Console.WriteLine("person is Greeting");
}
However, Visual Studio is clever and it will give a warning to us:
The given expression is never of the provided
('Program.Person') type

Solved the problem, but the issue of always getting false was that Command (which is implemented in HelloCommand) is not a interfence, hence always false.
To solve this issue you can do
command.BaseType.IsEquivalentTo(genericType)

Related

C# Cannot convert from CResourceGroup to TResource

I have extracted this from the real code and just implemented some things to give it context (I hope). I get the following error on the line with the recursive call to GetResourceVariable
CS1503: Argument 1: cannot convert from `CResourceGroup` to `TResource`
Argument type `CResourceGroup` is not assignable to parameter type `TResource`
What I am trying to do is call GetResourceVariable on an object of type TResource to get a certain variable value. These objects are part of a hierarchy so if the variable is not defined on the resource I want to traverse up the hierarchy and see whether a 'parent' has this variable defined and return that value.
This is where FromResource comes in. Now this FromResource should a group/folder type resource, but that has much of the properties of a resource, which you can see from the class inheritance hierarchy.
I don't get why I can't use a CResourceGroup (which is a CResDefs which is a CResource as the parameter to the generic function that has a where TResource : CResource I thought that the where constraint meant that only objects that are CResource (or inherited from CResource) could be the parameter? Somehow this last part seems not true!
I might be able to refactor the inheritance hierarchy but before trying that I would rather know why this is not possible as shown in C#?
using System;
using System.Collections.Generic;
public class Program
{
public class CResVariable
{
public string Value { get; set; }
}
public class CResVariableList : List<CResVariable>
{
public CResVariable GetByName(string name) { return null; }
}
public class CResource {
public CResVariableList ResVariables { get; set; }
public CResourceGroup FromResource
{
get
{
return this.GetFromResource(useChildrenList:true);
}
}
protected CResourceGroup GetFromResource(bool useChildrenList = false)
{
return null;
}
}
public class CResDefs : CResource {}
public class CResourceGroup : CResDefs {}
public class ResVariableSupport {
public string GetResourceVariable<TResource>(TResource resource, string variableName, bool recursive)
where TResource : CResource
{
CResVariable variable = resource?.ResVariables?.GetByName(variableName);
if (variable != null)
{
return variable.Value;
}
if (recursive)
{
return this.GetResourceVariable<TResource>(resource?.FromResource, variableName, true);
}
return "";
}
}
public static void Main() {
Console.WriteLine("Hello world!");
}
}
The only problem in your code is explicitly naming the generic parameter in the call to GetResourceVariable - you dont need to do that as it is implied from the call.
This works:
return this.GetResourceVariable(resource?.FromResource, variableName, true);
Code here: https://dotnetfiddle.net/LxUIxL

Casting to a generic interface [duplicate]

I have the following classes
public abstract class BaseViewPresenter { }
public abstract class BaseView<T> : UserControl
where T : BaseViewPresenter { }
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> { }
I have a method that looks like this (simplified)
public BaseView<BaseViewPresenter> Resolve(BaseViewPresenter model)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
// Correctly creates BaseView object
var control = Activator.CreateInstance(viewType);
// Fails to cast as BaseView<BaseViewPresenter> so returns null
return control as BaseView<BaseViewPresenter>;
}
When I call this using an instances of LoginPresenter
var login = new LoginPresenter();
var ctl = Resolve(login);
The line Activator.CreateInstance(viewType) correctly resolves into a new instances of my LoginView, however control as BaseView<BaseViewPresenter> can't do the cast correctly so returns null.
Is there a way to correctly cast the control into BaseView<BaseViewPresenter> without using specific type generics?
Since LoginView inherits from BaseView<LoginPresenter>, and LoginPresenter inherits from BaseViewPresenter, I would assume there's a way to convert LoginView to BaseView<BaseViewPresenter>.
I am stuck with using .Net 3.5
This is a very frequently asked question. Let's rename your types:
abstract class Fruit { } // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { } // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> { } // was LoginView
Your question now is:
I have a BowlOfApples, which inherits from FruitBowl<Apple>. Why can I not use it as a FruitBowl<Fruit>? An apple is a fruit, so a bowl of apples is a bowl of fruit.
No, it isn't. You can put a banana in a bowl of fruit, but you can't put a banana in a bowl of apples, and therefore a bowl of apples is not a bowl of fruit. (And by similar argument, a bowl of fruit is not a bowl of apples either.) Since the operations you can legally perform on the two types are different, they cannot be compatible.
Here is a photo of StackOverflow legend Jon Skeet demonstrating this fact:
The feature you want is called generic contravariance, and it is supported only on interfaces and delegate types when the compiler can prove that the variance is safe, and when the varying type is a reference type. For example, you can use an IEnumerable<Apple> in a context where IEnumerable<Fruit> is needed because the compiler can verify that there is no way that you can put a Banana into a sequence of fruit.
Do a search on "C# covariance and contravariance" on this site or on the web and you'll find many more details about how this feature works. In particular, my series of articles on how we designed and implemented this feature in C# 4 starts here: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
I accepted Eric's answer since it provides a great explanation of why what I wanted wasn't possible, but I also thought I'd share my solution in case anyone else runs into this same problem.
I removed the generic type parameter from my original BaseView class, and created a 2nd version of the BaseView class that included the generic type parameter and specifics for it.
The first version is used by my .Resolve() method or other code that doesn't care about the specific types, and the second version is used by any code that does care, such as the implentation of a BaseView
Here's an example of how my code ended up looking
// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl
{
public BaseViewPresenter Presenter { get; set; }
}
public abstract class BaseView<T> : BaseView
where T : BaseViewPresenter
{
public new T Presenter
{
get { return base.Presenter as T; }
set { base.Presenter = value; }
}
}
// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter>
{
// Can now call things like Presenter.LoginPresenterMethod()
}
// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
BaseView view = Activator.CreateInstance(viewType) as BaseView;
view.Presenter = presenter;
return view;
}
You're expecting to treat the type as being covariant with respect to the generic argument. Classes can never be covariant; you'd need to use an interface rather than (or in addition to) an abstract class to make it covariant with respect to T. You'd also need to be using C# 4.0.
My usual solution to this problem is to create an intermediary class that has access to the type-parametric class's methods through delegates. Fields can also be accessed through getters/setters.
The general pattern goes:
public abstract class Super {}
public abstract class MyAbstractType<T> where T : Super {
public MyGeneralType AsGeneralType() {
return MyGeneralType.Create(this);
}
// Depending on the context, an implicit cast operator might make things
// look nicer, though it might be too subtle to some tastes.
public static implicit operator MyGeneralType(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
public int field;
public void MyMethod1() {}
public void MyMethod2(int argument) {}
public abstract bool MyMethod3(string argument);
}
public delegate T Getter<T>();
public delegate void Setter<T>(T value);
public delegate void MyMethod1Del();
public delegate void MyMethod2Del(int argument);
public delegate bool MyMethod3Del(string argument);
public class MyGeneralType {
public Getter<int> FieldGetter;
public Setter<int> FieldSetter;
public MyMethod1Del MyMethod1;
public MyMethod2Del MyMethod2;
public MyMethod3Del MyMethod3;
public static MyGeneralType Create<T>(MyAbstractType<T> t) where T : Super {
var g = new MyGeneralType();
g.FieldGetter = delegate { return t.field; };
g.FieldSetter = value => { t.field = value; };
g.MyMethod1 = t.MyMethod1;
g.MyMethod2 = t.MyMethod2;
g.MyMethod3 = t.MyMethod3;
return g;
}
public int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
The above exemplifies getting all the methods and fields but normally I only need a few of them. This is a general solution to the problem and one could feasibly write a tool to generate these intermediary classes automatically, which I might at some point.
Try it here: https://dotnetfiddle.net/tLkmgR
Note that this is enough for all my cases, but you can be extra hacky with this:
public abstract class MyAbstractType<T> where T : Super {
// ... Same everything else ...
// data fields must become abstract getters/setters, unfortunate
public abstract int field {
get;
set;
}
public static implicit operator MyAbstractType<Super>(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
}
public class MyGeneralType : MyAbstractType<Super> {
// ... same constructors and setter/getter
// fields but only keep method fields
// that contain the method references for
// implementations of abstract classes,
// and rename them not to clash with the
// actual method names ...
public MyMethod3Del myMethod3Ref;
// Implement abstract methods by calling the corresponding
// method references.
public override bool MyMethod3(string argument) {
return myMethod3Ref(argument);
}
// Same getters/setters but with override keyword
public override int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
And there you go, now you can literally cast a MyAbstractType<Sub> where Sub : Super to a MyAbstractType<Super>, although it's no longer the same object anymore, but it does retain the same methods and data, it's sort of a complex pointer.
public class Sub : Super {}
public class MySubType : MyAbstractType<Sub> {
public int _field;
public override int field {
get { return _field; }
set { _field = value; }
}
public override bool MyMethod3(string argument) {
Console.WriteLine("hello " + argument);
return argument == "world";
}
}
public class MainClass {
public static void Main() {
MyAbstractType<Sub> sub = new MyAbstractType<Sub>();
MyAbstractType<Super> super = sub;
super.MyMethod3("hello"); // calls sub.MyMethod3();
super.field = 10; // sets sub.field
}
}
This isn't as good in my opinion, the other version of MyGeneralType is a more straighforward layer over the concrete types, plus it doesn't require rewriting the data fields, but it does actually answer the question, technically. Try it here: https://dotnetfiddle.net/S3r3ke
Example
Using these abstract classes:
public abstract class Animal {
public string name;
public Animal(string name) {
this.name = name;
}
public abstract string Sound();
}
public abstract class AnimalHouse<T> where T : Animal {
List<T> animals;
public AnimalHouse(T[] animals) {
this.animals = animals.ToList();
}
public static implicit operator GeneralAnimalHouse(AnimalHouse<T> house) {
return GeneralAnimalHouse.Create(house);
}
public List<string> HouseSounds() {
return animals.Select(animal => animal.Sound()).ToList();
}
}
We make this "general" variant:
public delegate List<string> HouseSoundsDel();
public class GeneralAnimalHouse {
public HouseSoundsDel HouseSounds;
public static GeneralAnimalHouse Create<T>(AnimalHouse<T> house) where T : Animal {
var general = new GeneralAnimalHouse();
general.HouseSounds = house.HouseSounds;
return general;
}
}
And finally with these inheritors:
public class Dog : Animal {
public Dog(string name) : base(name) {}
public override string Sound() {
return name + ": woof";
}
}
public class Cat : Animal {
public Cat(string name) : base(name) {}
public override string Sound() {
return name + ": meow";
}
}
public class DogHouse : AnimalHouse<Dog> {
public DogHouse(params Dog[] dogs) : base(dogs) {}
}
public class CatHouse : AnimalHouse<Cat> {
public CatHouse(params Cat[] cats) : base(cats) {}
}
We use it like this:
public class AnimalCity {
List<GeneralAnimalHouse> houses;
public AnimalCity(params GeneralAnimalHouse[] houses) {
this.houses = houses.ToList();
}
public List<string> CitySounds() {
var random = new Random();
return houses.SelectMany(house => house.HouseSounds())
.OrderBy(x => random.Next())
.ToList();
}
}
public class MainClass {
public static void Main() {
var fluffy = new Cat("Fluffy");
var miu = new Cat("Miu");
var snuffles = new Cat("Snuffles");
var snoopy = new Dog("Snoopy");
var marley = new Dog("Marley");
var megan = new Dog("Megan");
var catHouse = new CatHouse(fluffy, miu, snuffles);
var dogHouse = new DogHouse(snoopy, marley, megan);
var animalCity = new AnimalCity(catHouse, dogHouse);
foreach (var sound in animalCity.CitySounds()) {
Console.WriteLine(sound);
}
}
}
Output:
Miu: meow
Snoopy: woof
Snuffles: meow
Fluffy: meow
Marley: woof
Megan: woof
Notes:
I added names so it's clear that the method references carry their owner's data with them, for those unfamiliar with delegates.
The required using statements for this code are System, System.Collections.Generic, and System.Linq.
You can try it here: https://dotnetfiddle.net/6qkHL3#
A version that makes GeneralAnimalHouse a subclass of AnimalHouse<Animal> can be found here: https://dotnetfiddle.net/XS0ljg

Using expression tree call a method with the same name on 2 unrelated classes

Suppose I have a base class like the following
public abstract class BaseHelloWorld<T> where T : BaseEntity
{
public abstract IEnumerable<T> DoSomething();
}
and another like
public class BaseEntity
{
public abstract void DoSomethingInPayload();
}
Then I have 4 classes like:
public class Payload1 : BaseEntity
{
public override void DoSomethingInPayload()
{
Console.Write("Hello world");
}
}
public class Class1 : BaseHelloWorld<Payload1>
{
public override IEnumerable<Payload1> DoSomething()
{
return new List<Payload1> { };
}
}
public class Payload2 : BaseEntity
{
public override void DoSomethingInPayload()
{
Console.Write("Goodbye world");
}
}
public class Class2 : BaseHelloWorld<Payload2>
{
public override IEnumerable<Payload2> DoSomething()
{
return new List<Payload2>() { };
}
}
Although I have shown code here, suppose these where third party libraries that I don't have code for and I want to extend them. What I want to do is to be able to create a single extension method that will allow me to call the DoSomethingInPayload() method on the payload class similar to
public static void CallDoSomething<T>(this BaseHelloWorld<T> theClass) where T: BaseEntity
{
theClass.DoSomethingInPayload();
}
Obviously this will not work so I started looking at expression trees. My reading suggests this is possible to do with expression trees but I cant figure it out. After hours of trying and getting nowhere I am unsure if my theory is correct. Therefore could you please tell me:
A) Is it possible to do this with expression trees
B) If so how would I do it?
Thanks in advance
Your own example is not working because T is a different type in the input and return parameters.
Indeed, as #AleksAdreev mentioned, you could simply try:
public static IEnumerable<T> CallDoSomething<T>(this BaseHelloWorld<T> theClass)
{
return theClass.DoSomething();
}
Which can then be called as follows:
var someClass = new Class2();
var someResult = someClass.CallDoSomething();

C# How could a superclass return back 3 possible types without casting from the calling class

Before I begin, I want to state I realize this isn't the ideal way of doing this. However the calling class can't be changed according to the rules of the assignment. I have tried to understand and find a solution to this problem, but I have had no luck.
Below there is 1 superclass,TreeMangement (There can only be 1 superclass for these subclasses). There are 3 subclasses(apple, orange and banana). The "find" method must be in the TreeMangement superclass. I am not allowed to override the "find" method. With the current code, I will get a casting error in the calling class. It will state that a TreeMangement can't implicity be casted into a AppleTree,OrangeTree or BananaTree.
Now my question is, am I able to somehow pass the correct type back to the calling class no matter what type (Apple,Banana,Orange) is calling it, without casting in the calling class? If so, how? If not, references so I know there is absolutely no way of doing it.
public class TreeMangement
{
public string id {get; set;}
public TreeMangement()
{
id = this.GetType().Name+"|"+Guid.NewGuid();
}
public static TreeMangement Find(string idIn)
{
string type = idIn.Split('|')[0];
return Functions.GetObj(idIn, GetFilePath(type), type); //returns back the right type
}
}
public class AppleTree:TreeMangement
{
public string Name;
}
public class OrangeTree:TreeMangement
{
public string Name;
}
public class BananaTree:TreeMangement
{
public string Name;
}
///////Calling class////
AppleTree savedAppleTree = AppleTree.Find("SomeValidID");
OrangeTree savedOrangeTree = OrangeTree.Find("SomeValidID");
BananaTree savedBananaTree = BananaTree.Find("SomeValidID");
You can change the superclass to a generic superclass like this:
public class TreeMangement<T>
where T: class
{
...
public static T Find(string idIn)
{
return ... as T;
}
}
Now you are able to specifiy the return type in your subclasses like
public class AppleTree:TreeMangement<AppleTree>
{
public string Name;
}
public class OrangeTree:TreeMangement<OrangeTree>
{
public string Name;
}
public class BananaTree:TreeMangement<BananaTree>
{
public string Name;
}
This way your 3 find calls will compile just fine as the Find() call will return the correct type:
var savedAppleTree = AppleTree.Find("SomeValidID");
var savedOrangeTree = OrangeTree.Find("SomeValidID");
var savedBananaTree = BananaTree.Find("SomeValidID");

Casting a generic class without specific type

I have the following generic class
public class Home<T> where T : Class
{
public string GetClassType
{
get{ return T.ToString() }
}
}
Now, I'm getting an Object X which I know for sure is Home:
public void DoSomething(object x)
{
if(x is // Check if Home<>)
{
// I want to invoke GetClassType method of x
// but I don't know his generic type
x as Home<?> // What should I use here?
}
}
Can I even make a cast without specifying the generic type of the class?
If you're sure the argument to DoSomething will be a Home<T>, why not make it a generic method?
public void DoSomething<T>(Home<T> home)
{
...
}
Of course, it would be even easier if DoSomething should logically be an instance method on Home<T>.
If you really want to stick with what you have, you could use reflection (untested):
public void DoSomething(object x)
{
// null checks here.
Type t = x.GetType();
if (t.IsGenericType &&
&& t.GetGenericTypeDefinition() == typeof(Home<>))
{
string result = (string) t.GetProperty("GetClassType")
.GetValue(x, null);
Console.WriteLine(result);
}
else
{
... // do nothing / throw etc.
}
}
What if Home derived from a base class?
public class Home
{
public virtual string GetClassType { get; }
}
public class Home<T> : Home
where T : class
{
public override string GetClassType
{
get{ return T.ToString() }
}
...
}
and then
public void DoSomething(object x)
{
if(x is Home)
{
string ct = ((Home)x).GetClassType;
...
}
}
How about making the function generic?
public void DoSomething<T>(object x)
{
if(x is Home<T>)
{
x as Home<T> ...
}
}
Edit:
Another possiblity would be to create an interface which holds the property GetClassName so you would only need to check if it is of that interface.
public interface IDescribeClass
{
public string GetClassName { get; set; }
}
BTW: I would use the full qualified name
public string ClassType
{
get{ return typeof(T).FullName; }
}
Have you tried changing your method definition to something like this?
public void DoSomething<T>(Home<T> x)
{
}
I know this is an old thread but all answers posted so far have not directly addressed this question and instead only suggested workarounds (i.e. "use reflection", "make your DoSomething() method generic" or "create a non-generic base class and call this base class' method").
Can I even make a cast without specifying the generic type of the class?
So to clearly answer your question: No it is not possible. Due to the covariance constraints in C# you cannot cast into a generic class.
In more detail: I am assuming you would want to use x as Home<object> as the lowest common denomitator in order to be be able to call toString() provided by the Object class. Casting your object x to Home<object> would require covariance which is not possible with classes (only generic interfaces and delegates can be covariant). while this is great to prevent mistakes at compile time, it is certainly an annoyance when wanting to access methods on generic classes, as in your case. #n8wrl answer is probably your best shot in terms of "casting".
That being said, you could also go for an interface-based solution, using the out flag on your T parameter:
interface IHome<out T> {
string GetClassType { get; }
}
public class Home<T> : IHome<T> where T : class
{
public string GetClassType
{
get { return typeof(T).Name; }
}
}
Then this should work:
public void DoSomething(object x)
{
if(x is // Check if Home<>)
{
var y = x as IHome<object>;
var z = y.GetClassType;
}
}

Categories

Resources