I have an abstract class which is inherited by another class as following:
public abstract class Employee
{
public string name{ get; set; }
public string age { get; set; }
}
public class OtherEmployee : Employee
{
public OtherEmployee()
{
}
public string specialField{ get; set; }
}
This is what I am doing and somehow, not getting it done:
Employee otherEmployee= new OtherEmployee();
otherEmployee.specialField = "somevalue";
I am not provided with the access to specialField, whereas all the attributes of Employee are accessible. I know it is a trivial problem, but I have hit a roadblock here..
Employee doesn't know about specialField, only OtherEmployee does. You need to cast it to the right class to use specialField.
Employee otherEmployee = new OtherEmployee();
This doesn't give you an OtherEmployee but an Employee. To be able to use specialField do something like this:
(otherEmployee as OtherEmployee).specialField = yourValue;
You will not have access to specialField because the object is created with the base class reference. It will not have access to the Child class properties.
Though the object is instantiated with a child Class, the reference still points to base class. So the properties/skeleton will be of base class and it would not have memory allocated for child class structure.
You have to write in this way beacause you daeclare otheremployee variable as Employee Type, so it doesn't know about special field. So:
(otherEmployee as OtherEmployee).specialField = "somevalue";
Related
Let's say I have an interface:
interface IPerson
{
int Age { get; set; }
string Name { get; set; }
bool Alive { get; set; }
}
and a Class:
public class Person : IPerson
{
public int Age { get; set; }
public string Name { get; set; }
}
That would not compile since Person does not implement the Alive Property.
What I would like to know is if there is a way to have the same behaviour, if Person adds an extra property that is not found in its interface.
interface IPerson
{
int Age { get; set; }
string Name { get; set; }
}
and a Class:
public class Person : IPerson
{
public int Age { get; set; }
public string Name { get; set; }
public bool Alive { get; set; } <---- This should prevent it from compiling as well.
}
I would want it to not compile as well, or at the very least give me a compile warning.
No. Interfaces define what members an object must implement. They cannot define members that an object can't implement. You could potentially use your own custom, or third party code analysis tools, to identify cases like this, but there is nothing in the language itself that would support it.
No it is not possible. Are you not trying to define a class itself here? Why do you really need an interface?
However, what you can achieve is make calls to your interface and not your class by doing
IPerson person = new Person();
this way you limit the person object to access only the methods defined in your interface.
There is a way to do this, but not within the object and its a bit silly to use in construction of the object. Using Reflection, you can check the type of an instance of your object and iterate through its properties, throwing an exception if the count or names of properties do not match your desired instance. Please note that if you just check against the interface, implementing objects will pass, so you would check against the desired concrete type. I am on my phone or I'd add some sample code, will try to return to this later.
There is a way to do this, but not within the object and its a bit silly to use in construction of the object. Using Reflection, you can check the type of an instance of your object and iterate through its properties, throwing an exception if the count or names of properties do not match your desired instance. Please note that if you just check against the interface, implementing objects will pass, so you would check against the desired concrete type. I'm on my phone so no sample code. Will try to return to this later.
I am encounter with a situation where I need to copy the members of base class to derived class.
I have an Instance of Base class which are returning by some other service, the same class we have used as a base class for further classes.
When we crates an object of derived class I want to assign the already created instance of base class to derived class, I know we can not assign the base class object to derived class but I am still searching any other solution.
Any one has any Idea?
Example :
public class VBase
{
public string Type {get;set;}
public string Colour {get;set;}
}
public class Car : VBase
{
public string Name {get;set;}
public int Year {get;set;}
}
// This class instance I am getting from some other source
VBase mBase= new VBase();
mBase.Type = "SUV";
mBase.Colour = "Black";
//-------------------------------------------------------
Car myCar= new Car();
myCar.Name = "AUDI";
mBase.Year = "2016";
//here I want to copy the instance of base class to derived class some thing like this or any other possible way.
myCar.base=mBase;
It is not possible in naïve way.
I'd like to recommend to define constructor or static method. I personally do not recommend to use additional libraries like AutoMapper for this job as they could require some conversion and make code cumbersome.
public class Car : VBase
{
// Method 1: define constructor.
public class Car(VBase v) {
this.Type = v.Type;
this.Colour = v.Colour;
}
// Method 2: static method.
public static Car FromVBase(VBase v){
return new Car()
{
this.Type = v.Type;
this.Colour = v.Colour;
};
}
public string Name {get;set;}
public int Year {get;set;}
}
Without using reflection, if your classes are lightweight, and wont change overtime, then you could create a public property of Base in Car:
public class Car : VBase
{
public string Name
{
get;
set;
}
public int Year
{
get;
set;
}
public VBase Base
{
set
{
base.Type = value.Type;
base.Colour = value.Colour;
}
}
}
You can then easily pass through your base class like so:
myCar.Base = mBase;
I have created a dotnetfiddle here:
dotnetfiddle for this question
I have base class, and multiple derived classes, like that:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Parent : Person
{
public int Age { get; set; }
}
public class Child : Person
{
public int Grade { get; set; }
public Parent Father { get; set; }
public Parent Mother { get; set; }
}
Each class has a table in the DB, with an appropirate field.
When I want to obtain data from the DB, and initalize an Person's instance, I need to set value for each property, like that:
Name = reader["Name"].ToString();
Age = int.Parse(reader["Age"].ToString());
Now, I don't want to do that on each derived class, but do that generally in the base class.
What is the best way to do that? Thank you.
First of all, the best answer you can find here is: adopt an OR/M like Entity Framework, NHibernate or Dapper (or any other) and focus your efforts in your business instead of wasting your time in infrastructure details!
In the other hand, if you want an approach to solve your issue using your own code, I would say you need to create the concept of data mapper. It would be a class which should define mapping between relational and object-oriented counterparts.
This way, when you try to obtain a derived class, you instantiate base class and derived class data mappers, and you call them to obtain the entire column data:
DerivedClass derivedClassInstance = new DerivedClass();
DerivedClassDataMapper derivedMapper = new DerivedClassDataMapper(derivedClassInstance, dataReader);
derivedMapper.Fetch();
// Now your derivedClassInstance reference will contain an object which
// has both data from base and derived class...
Finally, I would say that both data mappers should inherit from a DataMapper base class where Fetch method should be marked as virtual (or abstract) in order to let derived data mappers add more mapping code (this way, base mapper will map properties to columns defined in the base class, derived class will override Fetch to add more mappings and so on...).
Anyway, you shouldn't reinvent the wheel because there're solid object-relational mappers.
I am working on an application which currently creates data entity objects from the results of a sql query. In the database 3 of the tables are very similar but have several different properties.
My initial plan was to create 3 different classes, even though each class is very similar. However when I came to create the method which returns a list of objects, I have hit a stumbling block as the return type will be different depending on which mode the application is in.
e.g.
public class A
{
public int Id {get;}
public string Name {get;}
}
public class B
{
public int Id {get;}
public string Name {get;}
public string ExtraInfo {get;}
}
public class MainScreen
{
...
this.resultsGrid.DataSource = LoadData();
}
I would prefer not to write one method to load a list of each data type.
What should the return type of LoadData() be, to allow it to be generic as possible.
What is the most elegant way of dealing with this scenario?
Thanks,
Sean
You should have inheritance to allow polymorphism, so you would have a base class that all entities included in the data binding derive from it.
Then, you can have a mid-base class to have some shared properties like Name and ID.
Base class:
public abstract class Entity
{
}
Entity with Name and ID:
public class NameAndIDEntity : Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
Entity with Name, ID and ExtraInfo:
public class NameIDAndExtraEntity : NameAndIDEntity
{
public string ExtraInfo { get; set; }
}
Entity with other information (can't be derived from NameAndIDEntity), derives from Entity so it can be included in the data binding:
public class OtherInformationEntity : Entity
{
public int Age { get; set; }
}
Finally, you can make the LoadData return type Entity.
Simples!
Create a class ListItem (with properties Id and Name, I presume). In your factory class/method, make instances of that class from the records into a List and bind the datasource to the list.
Don't be scared to create specialised classes for your UI.
UPDATE: Forgot to mention. Avoid inheritance as much as possible.
First you can create an inheitance tree in your project, where base class holds a shared/common properties among set of dfferent types
Second you can retrieve from the query anonymous type and after map it to a known type by mapping them to a real type, like from Jon Skeet's blog Horrible grotty hack: returning an anonymous type instance
That means that you need by the way know which query what type returns (can not avoid that), but this can reduce amount of fraction you need to add to your code, like from example:
static class GrottyHacks
{
internal static T Cast<T>(object target, T example) //CAST TO SPECIFIED TYPE
{
return (T) target;
}
}
class CheesecakeFactory
{
static object CreateCheesecake()
{
return new { Fruit="Strawberry", Topping="Chocolate" };
}
static void Main()
{
object weaklyTyped = CreateCheesecake(); //ANONYMOUS TYPE GENERATION
var stronglyTyped = GrottyHacks.Cast(weaklyTyped,
new { Fruit="", Topping="" }); //"MAPPING"
Console.WriteLine("Cheesecake: {0} ({1})",
stronglyTyped.Fruit, stronglyTyped.Topping);
}
}
I have a class like the below, I want to override the set value of "School,Country..etc.." property when some one sets a value , i don't want to change the student class but i need to do it in the base class and use it as a generic method
public class Student : BaseClass
{
public String School { get; set; }
public String Country{ get; set; }
}
ie:
When some one sets
Student.School="Harvard",
I need to store it as
Student.School="Harvard my custom value";
Note:
Basically calling OnPropertyChanged in base class rather than the main class.
If you want to do it with aspects, then try Postsharp
Basically you cannot override a non-virtual property. You can hide it by other property with the same name in the derived class, but this won't give you the desired effect if some other code accesses your object by the reference to the base class.
public class Student : BaseClass
{
private string _school
public string School
{
get { return _school; }
set
{
if(value == "Harvard")
value = "Harvard custom";
_school = value;
}
}
public String Country{ get; set; }
}
is that what you mean?
If the School property is in the BaseClass then you can either use the new keyword, or if you control the BaseClass, then you can add the virtual keyword to the School property there, and override it in the Student class.
This is just not doable by solely modifying BaseClass. Think about it this way: If it were possible to "annotate" automatic properties that easily, then we wouldn't need all those <rant>useless tons of</rant> manual property implementations for data model classes that implement INotifyPropertyChanged (same for DependencyProperties).
You need to provide hooks in your subclasses that your base class can use. Implementing PropertyChanged, which you already mentioned, is one possible solution, another one would be a simple method call:
public class Student : BaseClass
{
private string _school;
public String School
{
get { return _school; }
set {
_school = value;
DoMoreChanges(ref _school); // DoMoreChanges is defined in BaseClass
}
}
public String Country{ get; set; }
}
If you have lots of subclasses that need this, you can either use Visual Studio Code Snippets to create the code or T4 templates.
Since your base class does not have those properties you will not be able to modify them from within the base class using standard OOD patterns or principles.
Now if you move the properties to your base class either as normal properties or virtual properties you can modify what you do in the set block of the properties to do extra work.
However if you cannot move these to the base class, and you cannot modify the Student class, as you seem to imply in you question, then you could encapsulate the student class within a new class like StudentProxy or something and then have it expose similar properties that will then call into the real student class how you want.
For example:
public class StudentProxy
{
private Student _student;
public StudentProxy(Student student)
{
this._student = student;
}
public String School
{
get { return _student.School; }
set
{
_student.School = value + " my custom value";
}
}
public String Country
{
get { return _student.Country; }
set
{
_student.Country = value + " my custom value";
}
}
}