How to cast a List<MyModel> to List<object> [duplicate] - c#

This question already has answers here:
Shorter syntax for casting from a List<X> to a List<Y>?
(7 answers)
Closed 7 years ago.
I'm not sure if what I am trying to do is setup correctly so I am asking for help.
I have a base class, A, that has a public virtual MethodA(...).
In Method A I have the following statement:
var recordToValidate = GetBulkRecordsToBeValidated(profileId);
< more code that uses recordToValidate >
In the base class A I define GetBulkRecordsToBeValidated as follows:
internal virtual List<object> GetBulkRecordsToBeValidated(int profileId)
{
throw new NotImplementedException();
}
I have other classes that inherit from Class A (i.e. Class B inherits from Class A, Class C inherits from Class A, etc).
Each inherited class overrides the GetBulkRecordsToBeValidated which makes a call to the database to return the specific records for that entity. Each entity returns a different model which is why in the base class I have the method return a List of object.
In Class B it looks like this:
internal override List<object> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelBRecords>
}
In Class C it looks like this:
internal override List<object> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelCRecords>
}
The problem is I am getting the following error in Class B and Class C on the return:
Cannot convert expression type System.Collection.Generic.List ModelBRecords to return type System.Collection.Generic.List object
What do I need to do so I can return different list types to the call to GetBulkRecordsToValidate in Method A of the Base Class A?

As a quick fix, use .Cast<Object>.ToList().
However, you might want to consider making the base class generic like this:
public class A<T>
{
public void MethodA()
{
List<T> recordToValidate = GetBulkRecordsToBeValidated(profileId);
....
}
internal virtual List<T> GetBulkRecordsToBeValidated(int profileId) // you might want to make this an abstract method instead of virtual
{
....
}
}
public class C : A<ModelCRecords>
{
internal override List<ModelCRecords> GetBulkRecordsToBeValidated(int profileId)
{
return makes call to database which returns a List<ModelCRecords>
}
}

You can create generic class
class A<T>
{
public virtual List<T> GetBulkStuff() { throw new Exception(); }
}
class B : A<ModelBRecords>
{
public override List<ModelBRecords> GetBulkStuff()
{
return base.GetBulkStuff();
}
}

Related

My child class's method not get called when initialised as Base

Think my understanding about OO is wrong.
Say I have these classes
public class BaseValidator{
public Result Validate(BaseRequest r){
xxxx
}
}
public class BaseRequest{
}
Then in my child class, I have this:
Public class ChildValidator : BaseValidator{
public Result Validate(ChildRequest r){
xxxx,
base.Validate(r);
}
}
public class ChildRequest: BaseRequest{
}
When using the classes:
BaseValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r);
I thought this will call ChildValidator's Validate method, but turned out it calls BaseValidator's method.
What is the right way to do this? I want to pass my ChildValidator to another method, which takes BaseValidator as a parameter.
You are currently casting ChildValidator to BaseValidator, as such you are calling BaseValidator.Validate(BaseRequest) which at present has a different signature to ChildValidator.Validate(ChildRequest). You can pass an instance of ChildRequest to either method without issue because it inherits from BaseRequest.
Without this cast you would call ChildValidator.Validate() as you are expecting:
ChildValidator cr = new ChildValidator();
ChildRequest r = new ChildRequest();
cr.Validate(r); // Calls ChildValidator.Validate() method
If you want the ChildValidator.Validate() method to always be called then you would need to use a virtual / override method. You can't do that as your classes are currently written because you are accepting different parameter types (BaseRequest and ChildRequest).
Interfaces
You could utilise interfaces to help you out in this case, as shown below:
public interface IValidator {
bool Validate(IRequest r);
}
public class BaseValidator : IValidator {
public virtual bool Validate(IRequest r) {
return true;
}
}
public class ChildValidator : BaseValidator {
public override bool Validate(IRequest r) {
return base.Validate(r);
}
}
public interface IRequest { }
public class ChildRequest : BaseRequest { }
public class BaseRequest : IRequest { }
With the above classes / interfaces the original calls would work as follows:
BaseValidator cr = new ChildValidator(); // cast to BaseValidator
ChildRequest r = new ChildRequest();
cr.Validate(r); // Still calls ChildValidator.Validate() method
Generic Class
Alternatively, and as Jon Skeet pointed towards, you may want to look at implementing a generic Validator class. That could perhaps look something like the below:
public class Validator<T> where T : BaseRequest {
public bool Validate(T r) {
return true;
}
}
public class BaseRequest { }
public class ChildRequest : BaseRequest { }
You can use that as below:
var validator = new Validator<ChildRequest>();
ChildRequest request = new ChildRequest();
validator.Validate(r);
The best method for you will depend on the rest of your implementation and what the methods are doing.

How to call generic method of derived class from base class reference in C#

I have the following base class (omitted version):
class BaseClass
{
}
I create the following derived classes:
class DataPreparationClass<T> : BaseClass
{
}
class DataClass<T,U> : DataPreparationClass<T>
{
public virtual void Start<U>(U arg)
{}
}
class DataClassMain : DataClass<InputData,Data>
{
public override void Start(Data argument)
{
base.Start(argument);
}
}
class DataClassAux : DataClass<InputData,AuxData>
{
public override void Start(AuxData argument)
{
base.Start(argument);
}
}
I have a List<BaseClass> containing various derived instances (there are more derived types) and I intend to call their Start method respectively:
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object arg = GetArgsForInstance(instance);
// instance.Start(arg); //can't call this
}
However, as their common base is the BaseClass, I can't call Start without casting to...basicly every possible type as their types are unknown at the processing.
If I use dynamic:
((dynamic)target).Start(new Data("starting")); //target is of type DataClassMain<InputData,Data>
I get an exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best
overloaded method match for
'Client.DataClass<InputData,Data>.Start(Data)' has some invalid
arguments'
So how should I call the unknown method?
So, the most straight forward answer to your question would be to use pattern matching to call the start method.
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object arg = GetArgsForInstance(instance);
switch(instance){
case DataClassMain d : d.Start((Data)arg); break;
case DataClassAux a : a.Start((AuxData)arg);break;
default: throw new Exception();
}
}
But I do get the feeling this is an convoluted and inappropriate inheritance chain, and you should really consider using a factory and/or strategy pattern instead.
It's assumed that GetArgsForInstance allways will return the correct type with respect to the type it receives as an argument, and that the return types (Data, AuxData and so on) share a common base type. So we could do the type resolution directly with a signature of T GetArgsForInstance<T>(BaseClass b). That way you can make sure you get args of the right type before you return it.
Since the Start overrides just pass along the call generic types, so the overrides in DataClassMain and DataClassAux are unnecessary.
If we modify DataClass a bit we can then do it like this:
class DataClass<T,U> : DataPreparationClass<T>
{
public virtual void Start(U arg)
{
//Do somethin with arg
}
public void Call(Func<BaseClass,U> f){
U data = f.Invoke(this);
Start(data);
}
}
and invoke it with
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
switch(instance)
{
case DataClassMain d : d.Call(GetArgsForInstance<Data>); break;
case DataClassAux a : a.Call(GetArgsForInstance<AuxData>);break;
default: throw new Exception();
}
}
The reason this is preferable is that we can let the compiler ensure that we only pass the appropriate types to the different methods, no casting needed.
But again, such a convoluted inheritance chain should almost always be avoided.
I would say, your questions shows multiple flaws in your model:
by definition of your classes, there is no polymorphism inbetween you Start() methods : Start(Data) do not override Start<U>(U)
by definition of your GetArgsForInstance() method, you have lost the type information you need.
I would add that Classes that are called Classes and Data that are called Data and that are parameterized with their content are way too generic.
That saying, your question implies that you are not wanting to fix those flaws, maybe they are out of your control, so you have to live with it :
instead of not loosing the Type information, you ask for a way to retrieve it.
instead of using polymorphism to retrieve the type from the best place to retrieve do so (in my opinion), which is the Start method itself, you ask for a way to retrieve it in the calling code.
So, what I would try to do is :
rework your GetArgsForInstance() method to be able not to loose this information, for instance, replace it by an object, something like :
class DataClassMain : DataClass<InputData,Data>
{
public override void Start(ArgumentProvider argumentProvider)
{
Data argument = argumentProvider.getArgumentAsData(argumentProvider);
base.Start(argument);
}
}
if not possible, retrieve the types from the inside of the derived classes, for instance something like :
public class DataClassMain : DataClass<InputData,Data>
{
public override void Start(object arg)
{
base.Start(arg);
Data argAsData = (Data) arg;
}
}
if not possible, that means you already have a set of constraint that is making your code hard to maintain, so let's go for a messy reflective thing, but you have to be aware that there is no polymorphism involved and get rid of your 'override' and 'virtual' modifier on Start() methods. Here is a fully working program, which output is :
DataClassMain
DataClassAux
public static void Main(string[] args)
{
List<BaseClass> instances = GetAllInstance();
foreach(BaseClass instance in instances)
{
object value = GetArgsForInstance(instance);
messyInvoke(instance, value);
}
}
private static void messyInvoke(BaseClass instance, object value)
{
MethodInfo method = instance.GetType().GetMethod("Start");
if (method != null)
{
ParameterInfo[] parametersInfos = method.GetParameters();
if (parametersInfos.Length == 1)
{
object[] paramArray = {value};
method.Invoke(instance, paramArray);
}
}
}
public class BaseClass{
public virtual Type GetTypeOfArgs()
{
return typeof(Toto);
}
}
public class DataPreparationClass<T> : BaseClass {}
public abstract class DataClass<T> : DataPreparationClass<T>
{
}
public class DataClassMain : DataClass<Toto>
{
public void Start(Data arg)
{
Console.WriteLine("DataClassMain");
}
}
public class DataClassAux : DataClass<Toto>
{
public void Start(AuxData argument)
{
Console.WriteLine("DataClassAux");
}
}
private static object GetArgsForInstance(BaseClass isntance)
{
if (isntance is DataClassMain)
return new Data();
if (isntance is DataClassAux)
return new AuxData();
throw new ArgumentException();
}
private static List<BaseClass> GetAllInstance()
{
return new List<BaseClass> {new DataClassMain(), new DataClassAux()};
}
public class Toto{}
public class DataClassInputData
{
}
public class Data : DataClassInputData
{
}
public class AuxData : DataClassInputData
{
}

Generic class with generic constructor? [duplicate]

This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 2 years ago.
I have a generic class. The constructor needs to accept an argument that is another instance of the same class. The problem is that the other instance can have a different generics type.
Looks like C# allows me to have a method with it's own generics type, but this doesn't appear allowed for the constructor.
public class MyClass<T>
{
public MyClass<T2>(MyClass<T2> parent = null)
{
}
// ... Additional stuff
}
The code above tells me T2 is undefined. It doesn't accept it as a method type.
One approach would be to add a second generic type to my class. But this is awkward and, in many cases, the argument will be null and there is not type.
Does anyone see a simple way around this?
Generic constructors aren't allowed. However, you can use a generic factory method instead.
public class MyClass<T>
{
public int Id { get; private set; }
public int? ParentId { get; private set; }
public static MyClass<T> Create(int id)
{
return Create<object>(id, null);
}
public static MyClass<T> Create<T2>(int id, MyClass<T2> parent = null)
{
var current = new MyClass<T>();
current.Id = id;
current.ParentId = parent?.Id;
return current;
}
private MyClass()
{
}
// ... Additional stuff
}
Sample use:
var intClass = MyClass<int>.Create(55);
var charClass = MyClass<char>.Create(234, intClass);
// charClass.ParentId is 55
This is only possible if you do not need to access any generic members of parent outside the factory method. If you do, you'd be better off abstracting it through a non-generic interface or base class.
You are correct. Generic constructors aren't supported.
You could probably try the following:
Create a lower level common interface
public interface IMyClass {
//...some common stuff
IMyClass Parent { get; set; }
}
And use that as the common link between the types
public class MyClass<T> : IMyClass {
public MyClass(IMyClass parent = null) {
Parent = parent;
}
public IMyClass Parent { get; set; }
// ... Additional stuff
}

Scaleable Fluent Interface with Inheritance

I am trying to write a Fluent Interface API that can scale well. What structure would allow for strong types, inheritance, and state-full(as in the class type)?
For instance
class A
{
public A PerformFoo()
{
//do stuff
return this;
}
}
class B : A
{
}
I would like class B when calling PerformFoo to return B not A, ideally I would prefer to stay away from
public class B : A
{
public new B PerformFoo()
{
return (B)base.PerformFoo();
}
}
As to not have to override or new Every method in child classes. I believe I would need to use generics that use Type signatures.
I don't want to use extension methods but can't seem to get the structure right when doing it with casting (T) like in the answer for [a link]Fluent interfaces and inheritance in C#
If I understand correctly, the issue is that Method1 is not behaving the way you'd like, as it downcasts to A, preventing you from calling further methods. One way around this is to shadow the method in subclasses:
public class A
{
public A Method1()
{
return this;
}
}
public class B : A
{
public new B Method1()
{
return (B)base.Method1();
}
}
finally i figured out the structure
public class A {}
public class B : A {}
public class C<T> : A where T : C<T>
{/*most methods return T*/}
public class D:C<D>
{/*all methods return this*/}
public class E<T>:C<T> where T:E<T>
{/*all methods return T*/}
public class F:E<F>{}
now even specialized generics will still return the original caller

Can Generics in base class be specified in the parent class

I have a base class that has methods that use a generic type in C#, I then have other classes that inherit from these, I want to specify the type in the parent class to avoid angle brackets everywhere...
Here's a sample method from my base class class CBaseHome
public List<T> fetchAll<T>(CBaseDb db, bool includeEmpty = true) where T : CBaseTable, new()
{
List<T> retVal = new List<T>();
...
return retVal;
}
I the have a parent class that inherits from this class, (without overriding this function)
In the class that then consumes this I have the following code...
List<student> students = new limxpoDB.Home.student().fetchAll<student>(db, false);
so the Home.student class here inherits the CBaseHome class, and student inherits the CBaseTable...
I'd like to be able to say in the Home.student class that the only valid generic type for that class is student so that my consuming code looks like...
List<student> students = new limxpoDB.Home.student().fetchAll(db, false);
I realise here that the difference is minute, but I also use this library in some VB>Net code where it looks terrible...
Any ideas?
Thanks
Generic type parameters on a method cannot be imposed by a child class. So if I have:
public class Parent {
public List<T> GetStuff<T>() { ... }
}
I can not do:
public class Child : Parent {
// This is not legal, and there is no legal equivalent.
public List<ChildStuff> GetStuff<ChildStuff>() { ... }
}
What you can do is make the parent class generic, rather than it's method:
public class Parent<T> {
public List<T> GetStuff() { ... }
}
public class Child : Parent<ChildStuff> {
// GetStuff for Child now automatically returns List<ChildStuff>
}

Categories