Is there a better way of doing the following ...
I have a base class which provides a default implementation of the DisplayName property. Obviously optionally set, not required.
Edit: I can't use an interface instead of this base class, because I have behavior in it, which is trimmed out in this example.
public abstract class BaseObject
{
public virtual string DisplayName { get; protected set; }
public BaseObject(string displayName)
{
if (!string.IsNullOrWhiteSpace(displayName))
{
this.DisplayName = displayName.Trim();
}
}
// There is common behavior, unrelated to DisplayName here ... trimmed out of this sample code.
}
I have a system object class, derived from BaseObject, but providing its own implementation of DisplayName
public class SystemObject : BaseObject
{
public override string DisplayName
{
get
{
return string.Format("TODO: Resources.{0}", this.Id);
}
// EDIT: Turns out I can't even do that, because EF can't materialize the property. So, it needs to be an empty protected setter.
protected set { throw new InvalidOperationException("Do not set this property!"); }
}
public SystemObject() : base(null)
{
}
}
and I have a user-defined object, derived from the same base class:
public class UserObject : BaseObject
{
public UserObject(string displayName) : base(displayName)
{
if (string.IsNullOrWhiteSpace(displayName))
{
throw new ArgumentNullException("displayName");
}
}
public void ChangeDisplayName(string newDisplayName)
{
if (string.IsNullOrWhiteSpace(newDisplayName))
{
throw new ArgumentNullException("newDisplayName");
}
this.DisplayName = newDisplayName.Trim();
}
}
which utilizes the DisplayName from BaseObject to store a user-provided display name.
I can't make the DisplayName in BasObject abstract, because I am doing EF code first.
I am particularly concerned about protected set { throw new InvalidOperationException("Do not set this property!"); }. Any way to avoid this?
Don't use an abstract class at all when you don't actually want to define any behavior. If you just want a way of saying that there are different objects with a DisplayName property getter, then create an interface that defines such a contract that these two classes can implement in their own ways.
I think I see where you are going with this.
Leave the property alone. Just make it a get-only property in the base class, but make the getter call an abstract method:
public string DisplayName { get { return GetDisplayName(); } }
Then declare the method as abstract:
protected abstract string GetDisplayName();
That will force your inheriting classes to provide an implementation of how to return a display name. You can then change your UserObject class to store the name internally during instantiation and return it in the implementation of the method.
You could simply stub it out to do nothing;
public string DisplayName { set {} ...}
Related
Code tells more than words, so look at this:
public abstract class ViewObject: INotifyPropertyChanged {
public virtual string Id {
get {
return this.GetType().Name;
}
}
}
public class Object : ViewObject {
private string id = string.Empty;
public override string Id {
get {
return this.id;
}
set {
this.id = value;
}
}
}
What is the correct way to implement the desired behaviour of a base implementation in the abstract class (yes, it should have a base implementation for this, but not for other things)?
I can only think of using the new keywork instead of override to simply hide the base implementation, but is this right?
you are already using inheritance. Override method is useful when method name and parameter is same.
here you can use method overloading.
for method overload name is same but parameter is different. you can use in inheritance also.
i hope this is useful
If you use the new keyword and someone casts your derived object to the base class, the base implementation will be called and not the derived one. To avoid this, the override is needed.
But that is currently not possible, cause your base class doesn't support a setter. So stick to the override and implement a set method in the base class that simply throws a NotSupportedExecption.
public abstract class ViewObject
{
public virtual string Id
{
get { return this.GetType().Name; }
set { throw new NotSupportedException(); }
}
}
public class Object : ViewObject
{
private string id = string.Empty;
public override string Id
{
get { return this.id; }
set { this.id = value; }
}
}
I wanna see if there is anyway that when the child property method is being called, it will call the parent property as well.
Note that the child is generated by a code generator from edmx. So I can't change anything except adding a partial class for the child class. (It might be too trouble to change the generator.)
The situation I am having :
I have a class "MyClass" that is automatically generated from the database. I can't change anything on it except adding a partial class or change the code generator.
Now, I need to "do something" whenever the property Name is being called. I am thinking if I can put a parent there and make it call the parent to do "something" when the child property is "Name" is being called.
What I want :
public class ClassBase
{
public string Name
{
get
{
CallMethod();
return Name;
}
}
}
public class MyClass : ClassBase
{
public string Name { get; set; }
}
MyClass myClass = new MyClass();
myClass.Name; < -- this will call the parent as well.
Is there anyway to do it?
Thanks in advance
Not really related but since you're not strictly using automatic properties in ClassBase, you should create a private string variable for Name. Something like _name or whatever your internal coding standards dictate.
public class ClassBase
{
private string _name;
public virtual string Name
{
get
{
CallMethod();
return _name;
}
set
{
_name = value;
}
}
}
public class MyClass : ClassBase
{
//Pretty pointless really since you're not doing anything with MyClass.Name.
public new string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
MyClass myClass = new MyClass();
myClass.Name; <-- this will call the parent as well.
Based on "can't change base class" comment there is pretty much nothing you can do to make some code to be executed instead/before/after base class because your property/method will not be called when your new class used as base class (see sample in details part).
Potential solution : if you need to extend specially designed parital class's and it provides extension poinst like CallMethod is marked as partial - it is expected for implemnting portion of the class to implement it :
partial public class ClassBase
{
partial void CallMethod();
public string Name {get {CallMethod(); return "";}}
}
// in generated portion of "ClassBase"
partial public class ClassBase
{
partial void CallMethod() { /* do something here */ }
}
Answer to exact "how to call base class property" is to use base, but hiding property/method this way is confusing (see below):
new public string Name { get { return base.Name;} }
Note that you can't use automatic property in derived class case as you explicitly want some additional code to be executed. If you need set in derived class you need own backing field like:
private string derivedName;
new public string Name {
get { return base.Name + derivedName;}
set { derivedName = value;}
}
Details:
As said in comments hiding base class' properties/methods leads to very confusing behavior. For you case (slightly updated base class with baking field as original sample had infinite recursion):
public class ClassBase
{
private string name;
public string Name
{
get
{
CallMethod();
return name;
}
}
}
You can try to hide Name property in derived class:
public class MyClass : ClassBase
{
// notice "new" to show comiler you know what you doing
// otherwise you'll get warning (but behavior will be the same)
new public string Name { get; set; }
}
The issue with hiding is that base class' method is still easily callable and likely be called by mistake if using derived class as base class:
MyClass myDerved = new MyClass();
ClassBase myDervedAsBase = myDerved;
var name = myDerived.Name; // calls MyClass.Name
var name = myDerivedAsBase.Name; // calls ClassBase.Name
This can be solved by making base class' method/property virtual - but it requires change in base class:
public class ClassBase
{
virtual public string Name { get {... } }
}
public class MyClass : ClassBase
{
override public string Name { get { ... } }
}
If you need to call base class' method/property from derived class usebase.MethodName() like:
override public string Name { get
{
// do some new stuff here
var baseName = base.Name;
// maybe even change result
return baseName;
}
}
If you expect most derived classes to need such behavior it could be better to design base class explicitly to enforce such behavior. For example you can have property to call virtual method before/after computing the value to return like:
public class ClassBase
{
virtual protected string AboutToReturnName(string result)
{
return name;
}
public string Name
{
get
{
var result = "MyName";
return AboutToReturnName(result);
}
}
}
More ideas:
Alternative to virtual is partial methods which works when instead of deriving class is combined from many "partial" parts like ASP.Net pages - see Partial Classes and Methods
If you need notifications around change of property - consider implementing INotifyPropertyChange
if you need to know when properties/method are called in general - consider using interfaces and automatically generate wrapper classes that have pre/post callback. I.e. mocking frameworks (like EasyMoq or RhinoMock) and DI containers (like Unity) provide and use such functionality.
You cannot do it without modifying the code generator. The modification would have to generate a call base.Name.
You can override the property in your subclass with the new operator.
public class MyClass : ClassBase
{
public new string Name { get; set; }
}
I have a situation like this:
public abstract class BaseClass
{
public abstract string MyProp { get; }
}
Now, for some of the derived classes, the properties value is a synthesized values, so there is no setter:
public class Derived1 : BaseClass
{
public override string MyProp { get { return "no backing store"; } }
}
This works fine. However, some of the derived class required a more traditional backing store. But, no matter how I write it, as on automatic property, or with an explicit backing store, I get an error:
public class Derived2 : BaseClass
{
public override string MyProp { get; private set;}
}
public class Derived3 : BaseClass
{
private string myProp;
public override string MyProp
{
get { return myProp;}
private set { myProp = value;}
}
}
Derived2.MyProp.set': cannot override because 'BaseClass.MyProp' does not have an overridable set accessor
How do I get this to work??
The best thing you can do is implement the property as virtual instead of abstract. Make the get and set blocks for each throw NotSupportedException in the base class and override the behaviour accordingly in derived classes:
public virtual string MyProp {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
Basically, you cannot. By adding a setter you are changing the definition of the property, so it does not really "override" the base property. It's the same as if you tried to override a method and add another parameter to it - they would be treated as different methods (overloaded). Since properties cannot be overloaded this won't work.
You'll just have to add another method to set the value (perhaps with protected accessibility).
Bradley's suggestion is good, but one thing I've done in cases where only the Setter should be virtual is to do something this this:
public class Root
{
private string _MyProp;
public string MyProp
{
get { return _MyProp;}
set { _MyProp = SetMyProp(value); }
}
protected virtual string SetMyProp(string suggestedValue)
{
return suggestedValue;
}
}
public class Child
: Root
{
protected override string SetMyProp(string suggestedValue)
{
string oReturn = base.SetMyProp(suggestedValue);
// Do some sort of cleanup here?
return oReturn;
}
}
It requires a little extra work up front, but it seems to maintain a higher degree of encapsulation (e.g. you can prevent subclasses from overriding the Getter behavior, and your subclass doesn't have to be aware of the underlying member behind the property).
I would suggest avoiding virtual or abstract properties. Instead, use a non-virtual property which chains to protected virtual or abstract get/set methods. Doing that will allow derived classes to override the methods and also shadow the property with one that has different access modifiers. Since the base property itself will be non-virtual, there will never be any need to override it, so the naming conflict with the new version won't matter.
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";
}
}
}
I have a nice interface, and I want to implement one member of it in a base class so the clients can derive from the base class and have less boiler-plate to write. However, even though declared abstract, the compiler complains that the class does not implement the interface?!? How is this supposed to be done?
Code in question:
public interface ITaskDefinition
{
ITask CreateTask(TaskId id);
string Name { get; }
bool HasName { get; }
}
public abstract class TaskDefinitionBase : ITaskDefinition
{
private string name_ = null;
public void SetName(string name)
{
name_ = name;
}
public string Name
{
get
{
return name_;
}
}
public bool HasName
{
get
{
return name_ != null;
}
}
}
and the error I get is:
ITaskDefinition.cs(15,27): error CS0535: 'NetWork.Task.TaskDefinitionBase' does not implement interface member 'NetWork.Task.ITaskDefinition.CreateTask(NetWork.Task.TaskId)'
You must add an abstract stub of the method:
public abstract ITask CreateTask(TaskId id);
Inheritors can then override it to implement the interface.
When an object implements an interface it must obey all the constraints applied by the interface. This means that you must implement all properties and methods declared in the interface.
In your case you're missing the implementation of CreateTask. Also, you should note that C# use properties as opposed to Java for example that uses getters/setters. For this reason you don't need a SetName method.
You code should look something like this:
public abstract class TaskDefinitionBase : ITaskDefinition
{
private string name_ = null;
public abstract ITask CreateTask(TaskId id);
public string Name
{
get
{
return name_;
}
set
{
name_ = value
}
}
public bool HasName
{
get
{
return name_ != null;
}
}
}
TaskDefinitionBase needs to include CreateTask - if you don't want to implement it, just mark the method as abstract to force any implementing classes to implement it.