I'm creating a form to manage the reports of my application, the idea is that every report form inherits from this base form. My problem is that it contains several properties that HAVE to be assigned and i need to verify on every child form if I already called all, so... I'm wondering if there is a way to automatically make a call to all those properties.
This is part of the controller code:
public abstract partial class ReportsController()
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
etc...
protected abstract void New();
protected abstract void Edit();
protected abstract void Print();
}
As you can see, methods are not a problem, they are abstract so they will have to be declared (and thanks to Resharper i will be warned if i missed one).
Child form:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
code...
}
protected override void New()
{
code...
}
other methods...
}
And im looking for this:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
//Auto assigned properties.
Table = "";
Fields = "";
Condition = "";
Group = "";
Order = "";
Columns = new DataGridViewColumnCollection();
ComboboxFields = new SortedList<string, string>();
}
protected override void New()
{
code...
}
other methods...
}
I don't know if I'm being senseless here :/ and I really need to get out of this doubt and if is possible... then simplify my work.
If your goal is to ensure that your properties are initialized to some default value, just add a constructor to ReportsController and set the properties there.
Now I understand, if you need to enforce implementation you should do it with abstract properties, inherited classes should implement then, and can be implemented with auto-properties:
public abstract class A
{
public abstract int MyProperty { get; set; }
}
public class B : A
{
public override int MyProperty { get; set; }
}
Short answer is not in C#5.0, in C#6.0 you have Auto-Property initializers, but I think that this is not what you are looking for.
Assuming you need a parameterless constructor, you can create an Init abstract method that is called from your base constructor and do a check if your initialization missed a property. There you can throw an exception or show a visual message indicating the failure.
So in base you do:
public abstract partial class ReportsController()
{
public ReportsController()
{
InitializeComponent();
//now your method
Init();
CheckProperties();
}
protected virtual void CheckProperties()
{
if(Table==null)
addVisualErrorMessage("Table property missing");
//and so on
}
protected abstract void Init();
}
But maybe you have to rethink your design and provide a single class with all the properties, so you can create an abstract method that forces you to provide all these important properties overriding a single method:
public class ComplexProperties
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
}
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController()
{
InitializeComponent();
//now your method
Properties= Init();
CheckProperties();
}
protected abstract ComplexProperties Init();
}
In any case I would prefer having a base constructor with parameters:
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController(ComplexProperties properties)
{
Properties=properties;
CheckProperties();
}
}
And then initialize from the constructor:
public partial class MyReport:ReportsController
{
public MyReport():base(new ComplexProperties { Table="",...})
{
}
}
You could implement an interface for the properties that both the abstract base and the child classes need to implement.
Related
Is it possible to prevent a child class from having the same property name as a parent class?
For example:
public class Vehicle {
public string Title { get; set; }
public string Make { get; set; } // Honda, etc.
}
public class Car : Vehicle {
public string Title { get; set; }
public bool HasWarranty { get; set; }
}
I'd like the above to throw a build error saying that Vehicle already has a property named Title. Is this possible? If another developer on my team does a copy/paste from Car to make a Motorcycle class and decides to a Make property, while Vehicle already has Make as a property name, it feels like a DRY violation.
One simple way to enforce something like this is with Attributes. You can create the concept of having custom validations that run against your codebase on wakeup of your application.
Pseudo Code:
public abstract ValidationAttribute : Attibute
{
public abstract bool Validate(Type target);
}
------
public EnforceDistinctMembersAttribute : ValidationAttribute
{
string[] members;
public EnforceDistinctMembersAttribute(params string[] members)
{
this.members = members;
}
public override bool Validate(Type target)
{
if (target......
}
}
Create a method that will loop over all types, find all ValidationAttributes and call the Validate method of each one passing in the Type it was attached to. If you come across an issue, you can throw an exception or log or so on.
Remember this is only pseudo code and its only meant to get the idea across.
Usage:
[EnforceDistinctMembers] // or
[EnforceDistinctMembers(nameof(Title), nameof(Make))]
public class Vehicle {
public string Title { get; set; }
public string Make { get; set; } // Honda, etc.
}
public class Car : Vehicle {
public string Title { get; set; }
public bool HasWarranty { get; set; }
}
I have a rather simple problem, but I can't find a proper solution anywhere. I would like to specify an abstract object CustomValues as property in my abstract parent class. However, the class inheriting from it should be able to use a more specific type as an object for this property CustomValues. At first I thought I would solve the problem by an interface, but unfortunately that didn't work out either. How do you do something like that, that it works?
public abstract class MyAbstract {
public abstract object CustomValues { get; set; }
}
public class MyImplementation : MyAbstract {
public override MySpecificClass CustomValues { get; set; }
}
This will throw me three errors:
Missing implementation for getter
Missing implementation for setter
Type missmatch between type object and MySpecificClass
The solution suggested in the comments would look something like this. (I'm assuming CustomValues should be a collection of something.)
public class MyClass<T>
{
public ICollection<T> CustomValues { get; set; }
}
Or to ensure CustomValues itself cannot be reassigned, but can be accessed and added to:
public class MyClass<T>
{
public ICollection<T> CustomValues { get; } = new List<T>();
}
I think your original thought that use an interface (+ generic) was at the correct direction. In general you might want to add type constraints as well.
public interface ICustomValues {
....
}
public class MySpecificClass : ICustomValues {
....
}
public abstract class MyAbstract<T> where T : ICustomValues {
public abstract T CustomValues {
get;
set;
}
}
public class MyImplementation: MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}
Thanks to you all guys. I found the solution by using a generic properly:
public abstract class MyAbstract<T> {
public abstract T CustomValues { get; set; }
}
public class MyImplementation : MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}
I have two similar classes, so I made a parent class, and 2 classes which derive from it. The thing is that they are both trees of only their own type. So for now I have a parent class which holds a reference list of public IList<ParentTreeClass> Children { get; set; }. How can I change the ParentTreeClass to force it to be derived from ParentTreeClass not including it.
To give a bit more specific example, lets call the classes ParentTreeClass, ImportTree and ExportTree.
public class ParentTreeClass {
public ParentTreeClass Parent { get; set; }
public IList<ParentTreeClass> Children { get; set; }
// Other stuff.
}
public class ImportTree : ParentTreeClass {
// Some overrides.
}
public class ExportTree : ParentTreeClass {
// Some other overrides.
}
As said, once I have a ExportTree object, its children and parent should also be ExportTree and no other object.
I have thought about Generics like so:
public class ParentTreeClass<T> {
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
But this is not restrictive enought, since I want T to be a child of ParentTreeClass. I tried adding where T : ParentTreeClass. This does not work, cause it tells me to use where T : ParentTreeClass<T>, then I run into issues understanding the second T.
Can I force a tree to be instances of the same type which derives from ParentTreeClass?
It's fairly simple to do.
public class ParentTreeClass<T> where T : ParentTreeClass<T> {
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
public class ImportTree : ParentTreeClass<ImportTree> {
// Some overrides.
}
public class ExportTree : ParentTreeClass<ExportTree> {
// Some other overrides.
}
This has the drawback that you can go on to define a class like this:
public class ImportTree2 : ParentTreeClass<ExportTree> {
// Some overrides.
}
But, so long as you're careful with your definitions this works fine.
You could do like this:
public class ParentTreeClass<T> where T: ITree
{
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
public interface ITree
{
IList<ITree> Children { get; set; }
ITree Parent { get; set; }
}
public class ImportTree : ParentTreeClass<ITree>, ITree
{
// Some overrides.
}
public class ExportTree : ParentTreeClass<ITree>, ITree
{
// Some other overrides.
}
Restriction is not subclass of parent but it restricts T by ITree implementations only
I have a class from an external library which I need to extend into antoher class. Also the extensions should remain reusable, as I need them also to be implemented in other places.
As neither mixins nor multiple inheritance are supported in C#, whats the common way to solve this?
namespace ExtLib
{
public class Properties
{
public virtual int fieldN { get; set; }
}
}
namespace MyLib
{
public class Extensions
{
public virtual int fieldM { get; set; }
}
}
namespace MyProject
{
public class MyModel
{
// needs to have all fields from ExtLib.Properties AND MyLib.Extensions
}
public class MyOtherModel
{
// needs to have all fields from MyLib.Extensions,
// MyLib.Extensions should be reusable
}
}
I know a solution could be an interface IExtensions, however this leads to alot of duplication as the number of the fields of Extensions and Properties are quite high (and in the development phase they change alot).
Are there any best practices?
How about you just aggregate instances of these classes into MyModel?
public class MyModel
{
private Properties _properties;
private Extensions _ extensions;
public MyModel(Properties properties, Extensions extensions)
{
_properties = properties;
_extensions = extensions;
}
public Properties Prop
{
get { return _properties; }
}
public Extensions Ext
{
get { return _extensions; }
}
}
Alternatively, you can of course get rid of manual backing fields and use auto-implemented properties with a public getter and private setter.
All changes to Properties and Extensions will be automatically reflected in MyModel. Aggregation is a common way of using design patterns in an object oriented manner as opposed to class manner, which regularly uses multiple inheritance.
As for polymorphism issues, you can create a derived class, override any behavior you want and pass an instance of that class into the constructor.
Create an abstract class that is derived from ExtLib, then derive MyProject from your abstract class
namespace ExtLib
{
public class Properties
{
public virtual int fieldN1 { get; set; }
public virtual int fieldN2 { get; set; }
public virtual int fieldN3 { get; set; }
public virtual int fieldN4 { get; set; }
public virtual int fieldN5 { get; set; }
}
}
namespace MyLib
{
abstract class Extensions : Properties
{
public virtual int fieldM1 { get; set; }
public virtual int fieldM2 { get; set; }
public virtual int fieldM3 { get; set; }
public virtual int fieldM4 { get; set; }
public virtual int fieldM5 { get; set; }
}
}
namespace MyProject
{
public class MyModel : Extensions
{
// contains all fields from ExtLib.Properties AND MyLib.Extensions
}
}
I want to inherit some properties that are the same in 2 classes using interface or abstract class; I don't want to declare variable in child classes.
Is it possible to do this?
Parent Class:
interface IError
{
DateTime GETDATE { get; set; }
string ERROR_NUMBER { get; set; }
string ERROR_SEVERITY { get; set; }
string ERROR_STATE { get; set; }
string ERROR_PROCEDURE { get; set; }
string ERROR_LINE { get; set; }
string ERROR_MESSAGE { get; set; }
}
Child :
public class Business
{
public Business()
{
this.Id = -1;
this.Message = "";
}
public int Id { get; set; }
public string Message { get; set; }
}
Another child:
public class DbTools
{
//Another Class
}
I need parent properties in this two classes, but if change code like below, I should use another variable that I don't want to:
public class Business : IError
{
private DateTime m_GetDATE;//I don't want to declare another variable
public DateTime GETDATE
{
get { return m_GetDATE; }
set { GETDATE = m_GetDATE; }
}
}
Sounds like you want an abstract base class:
public abstract class ErrorBase : IError
{
public DateTime GETDATE { get; set; }
//...ditto all the other IError properties
}
Then you can just inherit that:
public class Business : ErrorBase
{
// all the ErrorBase properties are inherited
}
You could also make the base class properties virtual just in case you need to override them in the derived classes at any point.
The other thing you might consider is composing rather than inheriting. It doesn't seem all that natural that Business and DbTools should be inheriting from the same base class, so instead have a (non-abstract) ErrorBase class that implements IError and have Business and DbTools have an Error property:
public class ErrorBase : IError
{
public DateTime GETDATE { get; set; }
//...ditto all the other IError properties
}
public interface IHaveError
{
ErrorBase Error { get; set; }
}
public class Business : IHaveError
{
public ErrorBase { get; set; }
}
As a bonus, you could make IHaveError actually be IHaveErrors and have a List<ErrorBase> property allowing your objects to hold more than one error, which might be useful sometimes.