Contravariance in inheritance - c#

Is there a way to make a return type contravariant in inherited types? See the example code below. I need this for Entity Framework.
public class InvoiceDetail
{
public virtual ICollection<Invoice> Invoices { get; set; }
}
public class SalesInvoiceDetail : InvoiceDetail
{
//This is not allowed by the compiler, but what we are trying to achieve is that the return type
//should be ICollection<SalesInvoice> instead of ICollection<Invoice>
public override ICollection<SalesInvoice> Invoices { get; set; }
}

You can apply generics with corresponding constraints
public abstract class InvoiceDetailBase<T> where T : Invoice
{
public virtual ICollection<T> Invoices { get; set; }
}
public class InvoiceDetail : InvoiceDetailBase<Invoice>
{
}
public class SalesInvoiceDetail : InvoiceDetailBase<SalesInvoice>
{
}

Related

How to use setter option (get; set; ) for IList Properties in Realm Model?

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.

Entity Framework Code First - objects all inherit base class, how to exclude records with a disabled property

I have a bunch of DTO objects that all inherit from a DtoBase class with some properties like Id, CreatedDate, and Disabled.
public class MyAppContext : ApplicationDbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
}
public class A : Base
{
public bool LikesMilk { get; set; }
}
public class B : Base
{
public string Name { get; set; }
}
public class Base
{
public int Id { get; set; }
public bool Disabled { get; set; }
}
When it comes time to querying the DB, is there an extension method or something I could write in order to exclude all disabled records on all queries for all objects?
//both should exclude disabled records
db.As.FirstOrDefault(x => x.LikesMilk)
db.Bs.ToList()
I've done this pretty much the same way that is outlined in this article. http://www.codeguru.com/csharp/csharp/soft-deleting-entities-cleanly-using-entity-framework-6-interceptors.html
Essentially, you create an attribute to designate a column as your "IsDeleted" column (in your case, Disabled). Then you create an interceptor that does 2 things:
Intercept delete commands and change them to updates
Intercept all queries and filter out soft deleted entities.
I ended up using this NuGet package EntityFramework.DynamicFilters and it was really easy to implement.
https://www.nuget.org/packages/EntityFramework.DynamicFilters
using EntityFramework.DynamicFilters;
public class MyAppContext : ApplicationDbContext
{
public DbSet<A> As { get; set; }
public DbSet<B> Bs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Filter("IsDisabled", (Base x) => x.Disabled, false);
}
}
public class A : Base
{
public bool LikesMilk { get; set; }
}
public class B : Base
{
public string Name { get; set; }
}
public class Base
{
public int Id { get; set; }
public bool Disabled { get; set; }
}

C#: simple Multiple-inheritance / mixin replacement?

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
}
}

How to discover through Reflection the base-base-base class from a class?

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'.

inherited types cause an exception at select time entity framework5

I am using EF5 code first and have types as follows :
public class Region
{
public int Id { get; set; }
//...
}
public class Destination : Region
{
public virtual Origine Origine { get; set; }
//...
}
public class Origine : Region
{
public virtual IList<Destination> Destinations { get; set; }
//...
}
my EF context type :
public class JobAndPopulationContext : DbContext
{
public DbSet<Region> Regions { get; set; }
}
I would like to select all regions by doing a simple listing like this :
context.Regions.ToList();
I got this weird error message :
The relationship manager was defined with an owner of type 'JobAndMigration.Classes.Origine', which is not compatible with the type 'JobAndMigration.Classes.Destination' for the source role 'Origine_Destinations_Target' in the specified relationship, 'JobAndMigration.Repository.Origine_Destinations'.
What does that error mean ?
How could I solve this issue ?
Have a look at different inheritance types here
For TPT, consider changing your context to the following;
public class JobAndPopulationContext : DbContext
{
public DbSet<Destination> Destinations { get; set; }
public DbSet<Origins> Origin { get; set; }
}

Categories

Resources