I have a base class and derived class. Derived class has same property as base class but it needs always return same value/readonly
public class BaseClass
{
public int Id {get; set;}
public TransactionTypeEnum TransactionType {get; set;}
}
public class DerivedClass: BaseClass
{
public new TransactionTypeEnum TransactionType {get;} = TransactionTypeEnum.Credit;
}
The problem with this is when I cast derived class to base I of course end up with 2 properties: one from base and one from derived. I could also declare TransactionType property as virtual and then override it in derived class but then I'm forced to add setter method. What's the best course of action in this case? Create a mapper between these 2 classes ?
From my perspective, your desire violates the Liskov substitution principle (see here): your base class defines a settable TransactionType. Since every derived class inherits that behavior, you either shouldn't break it or remove the behavior - i. e. remove the setter. Maybe the derived class isn't a real inheritor?
Another approach could look like this (protected setter):
public class BaseClass
{
public int Id {get; set;}
public TransactionTypeEnum TransactionType { get; protected set; }
}
public class DerivedClass: BaseClass
{
public DerivedClass()
{
TransactionType = TransactionTypeEnum.Credit;
}
}
you can make the property in the BaseClass virtual and then override it in the DerivedClass using a lambda expression to avoid the setter.
public class BaseClass
{
public int Id {get; set;}
public virtual TransactionTypeEnum TransactionType {get; set;}
}
public class DerivedClass: BaseClass
{
public override TransactionTypeEnum TransactionType => TransactionTypeEnum.Credit;
}
Related
I have a base class MyBaseClass, with a wrapper class MyWrapperClass which is derived from that base class. The purpose of declaring wrapper class is to detaching the EntityFramework-related annotations, Id properties and navigation properties from the base class. The structure of base class and derived class are as follows:
public class MyBaseClass
{
public ClassA MyProperty { get; set; }
}
public class MyWrapperClass: MyBaseClass
{
public int Id { get; set; }
public new ClassAWrapper MyProperty { get; set; }
}
I cannot use virtual...override pattern on MyProperty, because of the differet types for MyProperty in base class and derived class.
Thus, i put new keyword before MyProperty property, and i expect the EntityFramework to create the model based on ClassAWrapper instead of ClassA.
But i get an error when trying to add-migration: "ClassA should have a key". While ClassA has not a key property, but ClassAWrapper has.
DbContext implementation is as follows:
public class MyDbContext : DbContext
{
public DbSet<MyDerivedClass> MyDerivedClass { get; set; }
...
}
Problem: I need to tell the EntityFramework to give up on the MyProperty class of the base class (which is of type ClassA), and look at the same property in the derive class (with type ClassAWrapper) when creating the model.
Try NotMapped and Key data annotations, like this:
public class MyBaseClass
{
[NotMapped]
public ClassA MyProperty { get; set; }
}
public class MyWrapperClass: MyBaseClass
{
[Key]
public int Id { get; set; }
public new ClassAWrapper MyProperty { get; set; }
}
Assume I have a class:
abstract class MyBaseClass {
[Attribute1]
[Attribute2]
public string Property1 {get; set; }
[Attribute3]
[Attribute4]
public string Property2 {get; set; }
}
In the child class, that extends this class I want to add new attributes to the Property1 and Property2, preserving attributes, declared in the parent class.
Is this possible?
abstract class MyBaseClass {
[Attribute1]
[Attribute2]
public virtual string Property1 {get; set; }
[Attribute3]
[Attribute4]
public virtual string Property2 {get; set; }
}
class NewClass:MyBaseClass
{
[Attribute5]
public override string Property1 {get;set;}
[Attribute6]
public override string Property2 {get;set;}
}
Ensure, that Attributes 1-4 use inherited = true
[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public class Attribute1 : Attribute
{
}
Yes, you can do this overriding Property1 and Property2. You obviously need to make them virtual in the base class:
class MyAttribute: Attribute {}
class YourAttribute: Attribute {}
class Base
{
[My]
public virtual void Foo() {}
}
class Derived: Base
{
[Your]
public override void Foo()
{
}
}
And now var attributes = typeof(Derived).GetMethod("Foo").GetCustomAttributes(); will return both MyAttribute and YourAttribute instances of Derived.Foo.
Do note that all GetAttribute type methods have an overload that lets you specify if you want inherited attributed to be included in the result or not. Default behavior is to include inherited attributes.
It is only possible if the attribute that you want to inherit is not specified with AttributeUsageAttribute.Inherited = false. For example, inherting the ObsoleteAttribute does not work:
abstract class MyBaseClass {
[Obsolete]
public virtual string Property1 {get; set; }
}
class Derived : MyBaseClass
{
public override string Property1 {get; set;}
}
In this example, you get the warning message:
Member 'Property1' overrides obsolete member 'Property1'. Add the
Obsolete attribute to 'Property1'
By default, attributes are set with the Inherit = True flag. So if you create a custom attribute, inheritance should work fine.
I'm just wondering if there is a way to Map Properties from a class to an interface with out changing their names.
Say you imported some entities from a Database
public partial class Post
{
public int PostId {get; set;}
}
public partial class Book
{
public int BookId {get; set;}
}
and an interface:
public interface IHasID
{
int Id {get; set;}
}
is there a way to inherit from this interface and just map the Properties using attributes like:
public partial class Post : IHasID
{
[MetadataTypeAttribute(typeof(IHasID.Id))]
public int PostId;
}
I just want a simple way to do this without wrapping all of the code or changing the database. Is there a way to wrap the parital class to point its property as an interface property?
You could create an ID property which gets and sets your object's appropriate ID, like this:
public partial class Post : IHasID
{
[NotMapped]
public int Id
{
get { return PostId; }
set { PostId = value; }
}
public int PostId { get; set; }
...
You would of course do the same thing for Book.
I'm not sure if it's worth pointing out just for the sake of knowledge that, if it were vb.net, you could do it just like this:
Partial Public Class Post
Implements IHasID
Public Property PostId As Integer Implements IHasID.Id
End Class
I have this abstract class:
public abstract class Task
{
public string ID {get; set;}
public string Name {get; set;}
public abstract class Options{};
public abstract void Execute();
}
I have other classes extending this class:
public class Copy : Task
{
public override void Execute()
{
Console.Write ("running");
}
}
I'd like each derived class to implement their own Options class so they can have their own parameters.
So Search class have to implement it's own Options class with the properties it needs, such as "includesubfolders", "casesensitive", etc..
Meanwhile Move task can implement it's own: "overwrite", etc..
Making properties and methods abstract in an abstract class force derived classes to implement their own but defining a nested abstract class or an interface in the same class does not force it's derived classes implement their own.
I can define each property individually in each derived class but that defeats the purpose since I like to query the properties in Task.Options later in the Execute method.
I tried dynamic object as well, but that brought whole other issues.
You can use a generic
public abstract class Options{};
public class CopyOptions : Options
{
}
public abstract class Task<T> where T : Options
{
public string ID {get; set;}
public string Name {get; set;}
public T Options { get; set; }
public abstract void Execute();
}
public class Copy : Task<CopyOptions>
{
public override void Execute()
{
Console.Write("running");
}
}
You can't enforce a nested class implementation, but you could add a property for the Options:
public abstract class Task
{
public string ID {get; set;}
public string Name {get; set;}
public Options Options {get; set;}
public abstract void Execute();
public abstract class Options{};
}
However there's no way to enforce that the implementation of the Options class be nested within the class that implements Task.
You can always throw a notimplementedexeption exception
I have 2 sets of 2 classes where each pair has a super/sub-class relationship, and the orthogonal pair has a dependency relationship. What I am trying to determine is what to do with the constructors and/or bodies of the properties to keep the model as simple as possible with minimal data duplication.
Here's the structure in code:
public class Base1 {
public List<Base2> MyBase2Things { get; set; }
// Do things with Base2 objects
}
public class Sub1 : Base1 {
public List<Sub2> MySub2Things { get; set; }
// Do things with Sub2 objects and also with Base2 objects
}
public class Base2 {
public Base1 MyBase1 { get; set; }
// Do things with the Base1 object
}
public class Sub2 : Base2 {
public Sub1 MySub1 { get; set; }
// Do things with the Sub1 object
}
I have considered overriding the base properties in the sub-classes, but that doesn't fit very cleanly because the properties in the sub-classes don't have the same signature and so I would have to add properties.
I have also considered setting the base property in the sub-class constructor and set methods, but there is no way for the sub-class property to be updated if the base-class's property is updated.
What other options are there, and which is the cleanest (and why)?
Note: The above code is greatly simplified to illustrate the problem. There are additional properties and methods on the real classes, but this subset is the essence of the trouble I'm having.
I agree with Yaur that generics may help. As far as your options and keeping the model simple as possible - this probably depends on the specifics like the responsibilities of your 4 classes.
Let's say you're dealing with parent/child relationships of various vehicles & vehicle parts.
Scenario 1: The inherited relationship brings in orthogonal capability.
public class ItemParent { // formerly Base1
public List<ItemChild> MyChildren {get; set;}
}
public class ItemChild { // formerly Base2
public ItemParent MyParent {get; set;}
}
public class Car : ItemParent { // formerly Sub1
public List<CarPart> MyParts {get; set;}
}
public class CarPart : ItemChild { // formerly Sub2
public Car ParentCar {get; set;}
}
Of course, Cars should specifically know about CarPart, not ItemChild. So you fall back on generics here.
public class ItemParent<T> where T : ItemChild {
public List<T> MyChildren {get; set;}
}
public class ItemChild<T> where T : ItemParent {
public T MyParent {get; set;}
}
public class Car : ItemParent<CarPart> {}
public class CarPart : ItemChild<Car> {}
public class Truck : ItemParent<TruckPart> {}
public class TruckPart : ItemChild<Truck> {}
You can call subclass.MyChildren[] just fine, or make a MyParts property which delegates to MyChildren.
In this example, I think the model is pretty simple due to the fact that the parent/child metaphor is pretty easy to grok. Plus, if you add Truck-TruckParts (or Household-Resident, Shape-Line, etc.) you're not really increasing the complexity.
An alternative here would be to move the parent/child "responsibility" to a collection object (possibly custom), like so:
public class ParentChildCollection<TParent, TChild> {}
public class Car {
private ParentChildCollection<Car, CarPart> PartHierarchy;
public List<CarPart> MyParts {get { return PartHierarchy.GetMyChildren(this); } }
}
public class CarPart {
private ParentChildCollection<Car, CarPart> PartHierarcy;
public Car ParentCar {get { return PartHierarchy.GetMyParent(this); }}
}
The downside here is that, while clean, Truck and Car might not share a lot of code (if that's what you were wanting).
Scenario 2: The inherited relationship is about specializing to a parallel item.
public class Car { // formerly Base1
public List<CarPart> MyParts {get; set;}
}
public class CarPart { // formerly Base2
public Car MyParent {get; set;}
}
public class Truck : Car { // formerly Sub1
public List<TruckPart> MyParts {get; set;}
}
public class TruckPart : CarPart { // formerly Sub2
public Truck MyParent {get; set;}
}
In this case, Truck and Car do share more code. But this starts running into signature problems that aren't easily solved even with generics. Here, I'd consider making the base class more generic (Vehicle-VehiclePart). Or consider refactoring this second scenario into the first scenario. Or use the collection for parent/child management and the inheritance stictly for Car-Truck code consolidation.
At any rate, I'm not really sure that either scenario matches your case. At least some factor are based on how you have (and how you can) arrange your relationships.
Generics may be able to help you with at least part of this... something like:
public class Base1<T>
where T: Base2
{
public List<T> MyThings { get; set; }
protected Base1(List<T> listOfThings)
{
this.MyThings = listOfThings;
}
}
public class Sub1 : Base1<Sub2>
{
public Sub1(List<Sub2> listofThings):
base(listofThings)
{
}
}
making it work where you need to subclass in both directions can get tricky (and messy) quickly, but will look something like:
// Base 1 hierachy
abstract public class Base1
{
protected abstract Base2 GetBase2(int index); //we can't return the list directly
}
public class Base1<Base2Type> :Base1
where Base2Type : Base2
{
public List<Base2Type> MyBase2s { get; set; }
protected Base1(List<Base2Type> listOfThings)
{
this.MyBase2s = listOfThings;
}
protected override Base2 GetBase2(int index)
{
return MyBase2s[index];
}
}
public class Sub1<MySub1Type,MySub2Type> : Base1<MySub2Type>
where MySub1Type : Sub1<MySub1Type,MySub2Type>
where MySub2Type : Sub2<MySub1Type, MySub2Type>
{
public Sub1(List<MySub2Type> listOfThings):
base(listOfThings)
{
this.MyBase2s = listOfThings;
}
}
public class Sub1 : Sub1<Sub1,Sub2>
{
public Sub1(List<Sub2> listofThings):
base(listofThings)
{
}
}
// base 2 hirachy
abstract public class Base2
{
protected abstract Base1 MyBase1 { get; }
}
public class Base2<Base1Type,Base2Type> : Base2
where Base1Type: Base1<Base2Type>
where Base2Type : Base2
{
public Base1Type myBase1;
protected override Base1 MyBase1{ get {return myBase1;} }
}
public class Sub2<Sub1Type, Sub2Type> : Base2<Sub1Type,Sub2Type>
where Sub1Type : Sub1<Sub1Type,Sub2Type>
where Sub2Type : Sub2<Sub1Type,Sub2Type>
{
}
public class Sub2 : Sub2<Sub1,Sub2>
{
}