C# Use a method from a base class with a different parameter - c#

I've already research a lot about the question and already know the direct answer. You can't override a base method with new parameter. Thing is, what I want to do is simple yet I don't know what to look for or if what I want to do is non-sense so if anybody can point me to a direction that would be great.
Here's what I want to do. I have a base class with a method call Create. This methods takes a Type argument and uses reflection to create the associate object with its properties. Its works great with whatever type I pass as an argument but now I want this method to return the said type pass in the parameter to add it to a list. Naturally I just added a return to the created model but I can't add a Type object to my List Student (My own type here). So what I tried was to create a derived class and in that class change the parameter from Type to Student. Obviously this doesn't work but now I am stuck. My base method works perfectly (other than the fact it doesn't return what I want) and I would like to only modify the return type on my derived class. Here's the snippet of the code. (NOTE: I am french)
abstract class ControllerBase
{
public virtual Type Create(ControlContainer controlContainer, Type typeToCreate)
{
dynamic returnObject = null;
//Stuff that creates my returnObject
return returnObject;
}
}
class StudentControl : ControllerBase
{
static public List<Student> Students{ get; set; }
public Type Create(ContainerControl containerControl, Type typeToCreate)
{
typeToCreate = typeof(Student);
return base.Create(containerControl, typeToCreate);
}
}
So, this is basically what I want to do. Transform the return type of my base method to another type in my derived class in order to add it to my Student list. I've looked around but don't really what to look for here. I can't use a <T> generic method here because reflection doesn't work on generic type.

Who said that reflection doesn't work with generics?
abstract class ControleurBase
{
public virtual T Créer<T>(ConteneurControle conteneurControle)
{
var actualType = typeof(T); // use this instead of the Type parameter
dynamic modele = null;
//Stuff that creates my model
return (T)modele;
}
}
class ControleurÉtudiant : ControleurBase
{
public static List<Étudiant> Etudiant { get; set; }
public Étudiant Créer(ConteneurControle conteneurControle)
{
return base.Créer<Étudiant>(conteneurControle);
}
}
By the way, you really shouldn't write code that's not in English. It makes it hard for anyone who doesn't speak French.

Related

How to understand this generic class defination with such type parameters constrain define in C# [duplicate]

Yesterday, I was explaining C#'s generic constraints to my friends. When demonstrating the where T : CLASSNAME constraint, I whipped up something like this:
public class UnusableClass<T> where T : UnusableClass<T>
{
public static int method(T input){
return 0;
}
}
And was really surprised to see it compile. After a bit of thinking, however, I figured it was perfectly legal from the point of view of the compiler - UnusableClass<T> is as much of a class as any other that can be used in this constraint.
However, that leaves a couple of questions: how can this class ever be used? Is it possible to
Instantiate it?
Inherit from it?
Call its static method int method?
And, if yes, how?
If any of these is possible, what would the type of T be?
This approach is widely used in Trees and other Graph-like structures. Here you say to compiler, that T has API of UnusableClass. That said, you can implement TreeNode as follows:
public class TreeNode<T>
where T:TreeNode<T>
{
public T This { get { return this as T;} }
public T Parent { get; set; }
public List<T> Childrens { get; set; }
public virtual void AddChild(T child)
{
Childrens.Add(child);
child.Parent = This;
}
public virtual void SetParent(T parent)
{
parent.Childrens.Add(This);
Parent = parent;
}
}
And then use it like this:
public class BinaryTree:TreeNode<BinaryTree>
{
}
Well.
public class Implementation : UnusableClass<Implementation>
{
}
is perfectly valid, and as such makes
var unusable = new UnusableClass<Implementation>();
and
UnusableClass<Implementation>.method(new Implementation());
valid.
So, yes, it can be instantiated by supplying an inheriting type as the type parameter, and similarly with the call to the static method. It's for instance useful for tree-like structures where you want to generically specify the type of children the node has, while it being the same type itself.
If any of these is possible, what would the type of T be?
They are all possible, and you are the one who is gonna determine what is the type of T.For example let's assume there is a type that inherits from UnusableClass<T>
class Foo : UnusableClass<Foo> { }
Now you can instantiate UnusableClass<Foo> because Foo satisfies the constraint:
UnusableClass<Foo> f = new UnusableClass<Foo>();
Then the type of T become Foo and if you try to call method you need to pass an instance of Foo.

How to call a known method of a generic object

Sorry couldn't find a relevant SO question.
I use Reflection to get a property (which is another object) of an object using:
public static T GetPropertyValue<T>(this object obj, string propertyName)
{
PropertyInfo prop = obj.GetType().GetProperty(propertyName);
return (T)prop.GetValue(obj, null);
}
I have a (Xero) Api that looks like:
public class XeroCoreApi : XeroApi
{
public AccountsEndpoint Accounts { get; }
public ContactsEndpoint Contacts { get; }
// ...
}
Where the Endpoints inherit a class that looks like:
public abstract class XeroUpdateEndpoint
{
public TResult Update(TResult item);
// ...
}
i.e. I can call updates on the specific entities:
Contacts.Update(...);
When I do call the GetPropertyValue() method I get the Endpoint object from an instance of the XeroCoreApi but I don't know it's methods (really I do, but the compiler doesn't) until run-time.
To obtain the Endpoint I run the command similar to:
var endpoint = _api.GetPropertyValue<object>("Contacts");
// For the sake of this example the "Contacts" is manually
// entered, violating the whole idea of generics
The problem is I can't do something like endpoint.Update(...) (since the endpoint is a var and some endpoint don't particularly inherit the Update() method).
Is it possible to run the method using Reflection? What might the syntax look like?
Summary:
How to call a method (Update()) of an object of type T (i.e. we don't know the object until run-time) using reflection?
E.g. endpoint.Update(...)
If I understand you correctly, you want generic type constraints (not reflection). This gives the compiler the proof that your type satisfies some conditions.
For example, an interface:
public interface IUpdateStuff {
void Update();
}
public class XeroCoreApi : XeroApi, IUpdateStuff {
// implementation here
}
Then you can constrain your generic type:
public TResult Update(TResult item) where TResult : IUpdateStuff ;
Now the compiler will let you:
public TResult Update(TResult item) where TResult : IUpdateStuff {
item.Update(); // <-- this is okay now.
}
EDIT: This assumes your generic type comes from the enclosing class.. which it appears to in your example.

Pass Json object as object of type System.Object or Interface not working

Class:
public class ClassNameA :ISomeInterface {
}
public class ClassNameB :ISomeInterface {
}
From javascript:
var reqP = { 'Id': id, 'Name':name };
var ReqParams = { 'ReqParams': reqP };
var obj = { 'ClassNameA': ReqParams };
makeAjaxCall("POST",
JSON.stringify(obj), '/ControllerName/someMethod/', 'html',
Action method looks like:
public ActionResult someMethod(object obj){
// call comes to this method but obj is not populated.
}
public ActionResult someMethod(ISomeInterface obj){
// call comes to this method but throws exception.
// Exception : Cannot instantiate interface. but i am passing class object.
}
from JavaScript I will pass object of a concrete class type which implements ISomeInterface so that I can have multiple implementations. Concrete Class can of any one of the two types.
Any Suggestions?
That won't work. The model binder needs a concrete type to be able to create an instance and bind the values.
object is a concrete type and can be created using Activator.CreateInstance, but it doesn't have any properties that will match the data you receive.
The interface (or abstract types) cannot be created, since they're not concrete types. It's a simple as that.
If the JSON contained some hint about the type, it migth be possible to implement a custom model binder to create the instances for you. You can read more about the model binding process here.
The default model binder is not going to be able to figure out what to do. Let's just go through the exercise with some sample interfaces to show why. Say you have this:
public ActionResult SomeMethod(ISomeInterface obj)
{
// ...
}
...and say you have these two implemenetations:
class ClassA : ISomeInterface
{
public string Name { get; set; }
public string Phone { get; set; }
}
class ClassB : ISomeInterface
{
public string Name { get; set; }
public string Email { get; set; }
}
...and say this JSON is posted:
{ "Name": "Some Value" }
How would the model binder know which class to use? Would it search all defined classes in all assemblies to find all implementations of the interface? And if so, even if it had smart selection logic based on properties, how would it select between ClassA or ClassB, both of which are compatible?
What you may want to do is either use a type like Dictionary<string, object> that you know will be compatible, dynamic, or go with a concrete class that is a union of everything you need. Alternately, you can create a custom model binder with its own logic for selecting the class you want to instantiate. See this question for more details.

"This" type in generic parameter for derived classes

Is there a way to specify in type parameters that a parameter is the type of the object instance?
For instance, to illustrate, I have:
public abstract class Model
{
public int Prop1 { get; set; }
}
For my example, I want to have a method that will return a property of the Model passed in (obviously this is a stupid method, but it gets the point across). I can make it work as an extension method:
public static class Extensions
{
public static U Property<T, U>(this T model, Expression<Func<T, U>> property) where T : Model
{
return property.Compile().Invoke(model);
}
}
this way I can have
public class DerivedModel : Model
{
public string Prop2 { get; set; }
}
and do
var myString = new DerivedModel().Property(a => a.Prop2);
This method seems like it should be part of the Model class, and look something like:
public T Property<T>(Expression<Func<ThisDerivedInstanceOfModel, T>> property)
{
return property.Compile().Invoke(this);
}
so that the same call to Property() that the extension method does can execute on an instance of a Model.
I realize that this is kind of bizarre and may simply not be a feature of C#, and the workaround extension method works perfectly well - but I'd much prefer to make this an instance method if possible, since seems 'better' to me.
Is there a way to specify in type parameters that a parameter is the type of the object instance?
Nope. Sorry. There are times when I can see it being useful, but it's not something you can do. I've had similar issues in the past :(

Why Is It That Generics Constraint Can't Be Casted to Its Derived Type?

It is quite puzzling to find out that Generics Constraint Can't Be Casted to Its Derived Type.
Let's say I have the following code:
public abstract class BaseClass
{
public int Version
{ get { return 1; } }
public string FixString { get; set; }
public BaseClass()
{
FixString = "hello";
}
public virtual int GetBaseVersion()
{
return Version;
}
}
public class DeriveClass: BaseClass
{
public new int Version
{ get { return 2; } }
}
And guess what, this method will return a compilation error:
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)baseClass;
}
I would have to cast the baseClass to object first before I can cast it to DerivedClass, i.e.,
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)((object)baseClass);
}
Seems to me pretty ugly. Why this is so?
First, you shouldn't be casting a base type variable to a derived type. It's not supposed to work, only the other way around.
Second, why it works via object, is because you remove the compile-time type checks. The compiler can check that a BaseType cannot be cast to DerivedType. But when a variable is object, the compiler leaves it assuming you know what you're doing. Even if it will compile, the code will then crash during execution.
The answer is simple: the compiler can't know that T in your FreeConversion method can be converted to DeriveClass.
As you already stated, the cheap trick is to first cast to object, then to the type you want to go. Ugly, but it works.
Apart from that, it may be that you are violating Liskov Substitution principle, nothing that will harm any animals but can drive your design towards unmaintainable code.
Third, a nice trick to let your base class expose the derived type is something like this:
public class Base<T> where T : Base<T> {
T IAmDerived;
}
public class Derived : Base<Derived> { }
First of all, in your generic method the type T could be a vale type or reference type. And the reason why it allows you to do via 'Object' is that, you're simply doing boxing-unboxing which works for any type in system.
Secondly.it will be a terrible idea to convert/cast a baseclass object into a derived class. You're violating the mechanics of OOP.
If you really want to return an object of type derived from the base class, here's one way possible - the solution is pretty much similar to what Frank has offered.
//This is how you create a function in BaseClass that returns the collection
//of DerivedTypes when called from an object of type derivedclass, no magic just Generics.
//**The BaseClass**
public class BaseClass<T>
where T : BaseClass<T>
{
public HashSet<T> GetHashSet()
{
HashSet<T> _hSet = new HashSet<T>();
//do some work
//create a HashSet<T> and return;
return _hSet;
}
}
//**The Derived Class**
public class DerivedClass : BaseClass<DerivedClass>
{
//you have the method inherited.
}

Categories

Resources