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.
Related
I retrieve a list with the type of IEnumerable<ViewmodelA> and need to cast this list to IEnumerable<ViewmodelB>. There are same and different properties in each viewmodel and I just want to map the same properties (Name and Surnmame). Is it possible using boxing or AutoMapper? I tried boxing but it is not working :(
IEnumerable<ViewmodelB> newList;
newList = (IEnumerable<ViewmodelB>)demoService.GetList(); //returns IEnumerable<ViewmodelA>
ViewodelA:
public class ViewmodelA {
public string Name { get; set; }
public string Surname { get; set; }
public string School { get; set; }
public string Number { get; set; }
}
ViewodelB:
public class ViewmodelB {
public string Name { get; set; }
public string Surname { get; set; }
public string Work { get; set; }
public string Address { get; set; }
}
You won't be able to cast ViewmodelA to ViewmodelB.
The first few options that come to my mind are:
make both classes inherit from the same base class,
make both classes implement an interface,
create a conversion mechanism between A and B.
For something so trivial as this operation I think I would just:
var modelbs = modelas.Select(
a => new Viewmodelb(){
Name = a.Name,
Surname = a.Surname
}
);
You could make both viewmodels inherit from a base that has the Name and Surname in it, though note that this wouldn't allow you to cast a modela into a modelb, you could only cast the modela into the base class.
Or you could provide a constructor in modelb that takes a modela object and pulls just the name/surname out of it and use it like:
var modelbs = modelas.Select(
a => new Viewmodelb(a)
);
Your class ViewmodelB would look like:
public class ViewmodelB {
public string Name { get; set; }
public string Surname { get; set; }
public string Work { get; set; }
public string Address { get; set; }
public ViewmodelB(ViewmodelA x){
Name = x.Name;
Surname = x.Surname;
//maybe initialize other properties here
}
}
You can only do:
IEnumerable<ViewmodelB> newList = demoService.GetList().Select(a => SomeMethodCreatingBFromA(a));
Where SomeMethodCreatingBFromA can be anything - call constructor, AutoMapper, whatever. Didn't use AutoMapper to much, but I suppose it has a method that converts between collections.
If you just want to use the common properties, create a base class or an interface, where you define the common properties and derive both classes from that. Then you can use the base class or interface.
Here are examples for #tymtam answer
Make both classes inherit from the same base class
Make both classes implement an interface
Create a conversion mechanism between A and B
{
/// <summary>
/// Using the same base class
/// </summary>
public class BaseClass
{
public string Property { get; set; }
}
public class ViewModelA : BaseClass
{
public string Property { get; set; }
}
public class ViewModelB : BaseClass
{
public string Property { get; set; }
}
/// <summary>
/// Using the same interface
/// </summary>
public interface BaseInterface
{
string Property { get; set; }
}
public class ViewModelA : BaseInterface
{
public string Property { get; set; }
}
public class ViewModelB : BaseInterface
{
public string Property { get; set; }
}
/// <summary>
/// Create a conversion mechanism. This can be done in either in ViewModelA or ViewModelB
/// </summary>
public class ViewModelA
{
public string Property { get; set; }
public static implicit operator ViewModelA(ViewModelB model) => new ViewModelA { Property = model.Property };
public static implicit operator ViewModelB(ViewModelA model) => new ViewModelB { Property = model.Property };
}
public class ViewModelB
{
public string Property { get; set; }
}
I have a model class that is extended from the realm object. In some cases, I use this model as both realm model and POST operations. Currently, the realm IList properties unable to support setter options. Is there any option or way to achieve this?
Here is my current code:
[JsonObject]
public class Product : RealmObject, IProduct
{
[MapTo("name")]
[JsonProperty("name")]
public string Name { get; set; }
[MapTo("skuDetails")]
[JsonProperty("skuDetails")]
public IList<SkuDetail> SkuDetails { get; }
}
My requirement :
[JsonObject]
public class Product : RealmObject, IProduct
{
[MapTo("name")]
[JsonProperty("name")]
public string Name { get; set; }
[MapTo("skuDetails")]
[JsonProperty("skuDetails")]
public IList<SkuDetail> SkuDetails { get; set; }
}
you need to derive your class according your need.
this is totally possible like the code below:
public interface ITest
{
IList<object> SkuDetails { get; }
}
public class OutTest : ITest
{
public IList<object> SkuDetails { get; set; }
}
Please note that extending property method is supported however opposite of it is not.
Ex:
public interface ITest
{
IList SkuDetails { get; set; }
}
public class OutTest : ITest
{
public IList<object> SkuDetails { get; }
}
is not possible.
I have an employee object:
public class CreateEmployee
{
public string FirstName { get; set; }
public string LastName { get; set; }
[Import(AllowDefault=true)]
public ExtendEmployee ExtendEmployee { get; set; }
}
public class ExtendEmployee
{
public string Id { get; set; }
}
I want to extend this ExtendEmployee during runtime using MEF.
[Export]
public class ExtendCreateEmployee : ExtendEmployee
{
public decimal Salary { get; set; }
}
My Question is: If I dont define this [Export], is there a way to
import the base class "ExtendEmployee" instead of the default null for
the import.
I considered decorating the base class with [Export] attribute but in that case, the import will consider both the classes and I have to filter the inherited class. This can be fine if there is a way to either choose from the base class or the inherited class.
Thanks
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.
I'm using interfaces in this case mostly as a handle to an immutable instance of an object. The problem is that nested interfaces in C# are not allowed. Here is the code:
public interface ICountry
{
ICountryInfo Info { get; }
// Nested interface results in error message:
// Error 13 'ICountryInfo': interfaces cannot declare types
public interface ICountryInfo
{
int Population { get; }
string Note { get; }
}
}
public class Country : ICountry
{
CountryInfo Info { get; set; }
public class CountryInfo : ICountry.ICountryInfo
{
int Population { get; set; }
string Note { get; set; }
.....
}
.....
}
I'm looking for an alternative, anybody would have a solution?
VB.NET allows this. So, you can create a VB.NET assembly only with the interface definitions that you need:
Public Interface ICountry
ReadOnly Property Info() As ICountryInfo
Public Interface ICountryInfo
ReadOnly Property Population() As Integer
ReadOnly Property Note() As String
End Interface
End Interface
As for the implementation, C# does not support covariant return types, so you must declare your class like this:
public class Country : ICountry {
// this property cannot be declared as CountryInfo
public ICountry.ICountryInfo Info { get; set; }
public class CountryInfo : ICountry.ICountryInfo {
public string Note { get; set; }
public int Population { get; set; }
}
}
If the end goal is to use this with dependency injection, what's wrong with injecting them into each other instead of nesting?
public interface ICountry
{
ICountryInfo Info { get; }
}
public interface ICountryInfo
{
int Population { get; set; }
string Note { get; set; }
}
and implement as:
public class Country : ICountry
{
private readonly ICountryInfo _countryInfo;
public Country(ICountryInfo countryInfo)
{
_countryInfo = countryInfo;
}
public ICountryInfo Info
{
get { return _countryInfo; }
}
}
public class CountryInfo : ICountryInfo
{
public int Population { get; set; }
public string Note { get; set;}
}
Then once you set up your bindings for ICountry & ICountryInfo, CountryInfo will inject into Country whenever Country is injected.
You could then restrict the binding, if you wanted, to only inject CountryInfo into Country and nowhere else. Example in Ninject:
Bind<ICountry>().To<Country>();
Bind<ICountryInfo>().To<CountryInfo>().WhenInjectedInto<Country>();
You can use namespaces like this:
namespace MyApp
{
public interface ICountry { }
namespace Country
{
public interface ICountryInfo { }
}
}
Then in MyApp namespace you can use Country.ICountryInfo which is close to your requirement. Also using alias helps make the code clear.
This will work just fine, no need to nest:
public interface ICountry
{
ICountryInfo Info { get; }
}
public interface ICountryInfo
{
int Population { get; }
string Note { get; }
}
If ICountryInfo has no reason to exist outside ICountry, then why shouldn't you just put the properties of ICountryInfo in ICountry and dismiss the idea of nested interfaces?
An interface that hasn't a meaning of its own without another interface doesn't make sense to me, as an interface on itself is useless if not implemented by a class.