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.
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; }
}
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;
}
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 a base class where a property has a ScriptIgnore attribute:
public class Base
{
public int Id { get; set; }
[ScriptIgnore]
public virtual string Name { get; set; }
}
I also have another class which inherits from the Base class:
public class Inherting : Base
{
public override string Name { get; set; }
}
I tried overriding the Name property but it is still not being serialized. Is there a way to override the ScriptIgnore attribute (ignore it in the inherting class)?
I tried overriding the Name property but it is still not being
serialized. Is there a way to override the ScriptIgnore attribute
(ignore it in the inherting class)?
Use ScriptIgnore's ApplyToOverrides property and set it to false:
[ScriptIgnore(ApplyToOverrides = false)]
public virtual string Name { get; set; }
Reference: ScriptIgnoreAttribute.ApplyToOverrides Property
Consider the following example:
public class BaseClass
{
public string StringInBaseClass {get;set;}
public int IntInBaseClass {get;set;}
}
public InheritingClass : BaseClass
{
public long LongInInheritingClass {get;set;}
public long ShortInInheritingClass {get;set;}
public long CharInInheritingClass {get;set;}
}
Now, what I want to do is serialize JUST the inheriting properties to a JSON string. For example, I want to somehow create a JSON object out of just the 3 properties in InheritingClass, but if I do:
InheritingClass a = new InheritingClass();
JavaScriptSerializer jss = new JavaScriptSerializer();
string jsonString = jss.Serialize(a);
The jsonString value will have all of the properties of the BaseClass as well as all of the properties of InheritingClass. I understand that is normal, because I am inheriting all of those properties. What I am looking to do is NOT include those inherited properties and build a JSON string out of ONLY the 3 properties in InheritingClass.
Is this possible?
Use the ScriptIgnoreAttribute on any property you don't want serialized with the JavaScriptSerializer. With this you can do the following in your inherited class to stop a property from the base class from being serialized:
public class BaseClass
{
public virtual string StringInBaseClass {get;set;}
public int IntInBaseClass {get;set;}
}
public class InheritingClass : BaseClass
{
[ScriptIgnore]
public override string StringInBaseClass
{
get
{
return base.StringInBaseClass;
}
set
{
base.StringInBaseClass = value;
}
}
public long LongInInheritingClass {get;set;}
public long ShortInInheritingClass {get;set;}
public long CharInInheritingClass {get;set;}
}
If you never want to serialize those properties (even when serializing the base class or other derived classes) you can add the ScriptIgnore attribute to the base class:
public class BaseClass
{
[ScriptIgnore]
public string StringInBaseClass {get;set;}
[ScriptIgnore]
public int IntInBaseClass {get;set;}
}
This code return properties(type of PropertyInfo[]) that inherited members are not considered:
typeof(InheritingClass).GetProperties(BindingFlags.DeclaredOnly)
Yuri is correct in how to get json to ignore the property.
However, there is no way to implicity ignore the properties of the base class, the inheriting class is the base class, that's how inheritance works.