In my ASP.NET Core API, I have a DTO class BaseDto and another DerivedDto that inherits from BaseDto and hides some of its properties, because they're required in DerivedDto. I also have a BaseModel class to which both BaseDto and DerivedDto will be mapped through another class Mapper.
Something like the following code:
using System.ComponentModel.DataAnnotations;
public class BaseDto
{
public string Name { get; set; }
}
public class DerivedDto : BaseDto
{
[Required]
public new string Name { get; set; }
}
public class BaseModel
{
public string NameModel { get; set; }
}
public static class Mapper
{
public static BaseModel MapToModel(BaseDto dto) => new BaseModel
{
NameModel = dto.Name
};
}
But it turns out, when passing a DerivedDto object to the MapToModel method, it's trying to access the values of the BaseDto (which are null) instead of the DerivedDto ones.
Is there any way I can achieve this behavior?
I can only think of declaring BaseDto as abstract, but that would prevent me from instantiating it, which I need to do.
You need to declare your BaseDto class property as virtual and then override it in the DerivedDto class as follows:
public class BaseDto
{
public virtual string Name { get; set; }
}
public class DerivedDto : BaseDto
{
public override string Name { get; set; }
}
Also, please fix your Mapper class method. There is no property Name in the BaseModel. It needs to be "NameModel = dto.Name"
Related
All of my models in all of my applications inherit from IEntity:
public interface IEntity
{
long Id { get; set; }
dynamic RelatedItems { get; set; }
}
To prevent NullReferenceException, I always write a constructor in each model:
public class Book : IEntity
{
public Book()
{
RelatedItems = new System.Dynamic.ExpandoObject();
}
// other properties of the book
}
I need the RelatedItems because my infrastructure does many things on it.
However, this boilerplate constructor is a true pain.
When C# introduced Default Implementation I thought maybe default constructors also exist now, thus I created a constructor in my IEntity interface.
But I got this error:
IEntity.cs(7,16): error CS0526: Interfaces cannot contain instance constructors
Is there a way that I can prevent this boilerplate code?
I once tried to change it to abstract base class but it messed with EF Core and its inheritance.
As #AlanK pointed out the easiest thing would be to create an abstract class providing a boilerplate implementation of your properties including any initializers like this:
public abstract class BaseEntitiy : IEntity
{
public virtual long Id { get; set; }
public virtual dynamic RelatedItems { get; set; } = new System.Dynamic.ExpandoObject();
}
you can then inherit your Book class from BaseEntity overriding properties as needed:
public class Book : BaseEntitiy
{
// example override if you need any special getters or setters for books
public override long Id
{
get => base.Id;
set
{
if (value > 0)
{
base.Id = value;
}
}
}
}
Take a look at this code.
It's better to use generic instead of dynamic, so I added a BookRelatedItem class which you can add any further properties to.
About the EntityBase class, it's an abstraction of your entities so you don't have to initialize your RelatedItems each time.
public interface IEntity<T> where T : class
{
long Id { get; set; }
IEnumerable<T> RelatedItems { get; set; }
}
public abstract class EntityBase<T> : IEntity<T> where T : class
{
public long Id { get; set; }
public IEnumerable<T> RelatedItems { get; set; }
public EntityBase()
{
RelatedItems = new List<T>();
}
}
public class Book : EntityBase<BookRelatedItem>
{
// other properties of the book
}
public class BookRelatedItem
{
//some props
}
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 have the following scenario:
public class BaseEntity {
public int Id { get; set; }
}
public class BaseAcademicEntity : BaseEntity { ... }
public class BaseFinancialEntity : BaseEntity { ... }
public class Student : BaseAcademicEntity {
public string Name { get; set; }
public Grade CurrentGrade { get; set; }
}
public class Grade : BaseAcademicEntity {
public string Description { get; set; }
}
Ok, now I'll discover the properties from Student class through Reflection.
foreach (PropertyInfo property in typeof(Student).GetProperties()) {
// Here I can discover the type of the current property.
var type = property.PropertyType;
// now, how to discover if this property is from BaseEntity type?
}
Like I wrote in the comment, how to discover if the property is from the BaseEntity type? Thanks!
The simplest way is to use Type.IsAssignableFrom:
if (typeof(BaseEntity).IsAssignableFrom(type))
Once you have a System.Type object, you can iteratively look at the 'BaseType' property until it is null or that it's 'BaseEntity'.