is there any way to use interfaces as navigation properties in EF6?
I've found related topics for EF4 or earlier where it didn't seem to be possible; generally, inheritance seems to have improved a lot since then, but I haven't found a way to make this specific problem work yet.
Example:
public interface IPerson
{
string name { get; set; }
}
public class Man : IPerson { /* ... */ }
public class Woman : IPerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
public virtual IPerson driver { get; set; } // This won't map
}
Is this possible in any way? If not, what'd be an advisable way to do this?
Because currently I don't see any way for an interface to have a set-able property whose type is some other interface (the IPerson property of ICar, for example), which kind of strikes me as a very serious design limitation?!
Okay, for those possibly facing the same issue in the future. After more testing around, this is how I'm doing it now.
public interface IPerson
{
string name { get; set; }
}
public abstract class APerson : IPerson
{
public string name { get; set; }
}
public class Man : APerson { /* ... */ }
public class Woman : APerson { /* ... */ }
public interface ICar
{
IPerson driver { get; set; }
}
public class Car : ICar
{
// This maps to the database
public virtual APerson driver { get; set; }
// And this implements the interface
ICar.driver
{
get
{
return (IPerson)driver;
}
set
{
if(!(value is APerson))
throw new InvalidCastException("driver must inherit from APerson");
driver = (APerson)value;
}
}
}
This gets a bit more tricky when having one-to-many / many-to-many relations, for that case I've written a class that inherits from Collection<Interface type>, but also implements ICollection<Abstract base type>, and again throws an exception when someone tries adding/setting any object that doesn't inherit from the abstract base class. It's basically a Collection<IPerson> that's guaranteed to only contain objects inheriting that inherit APerson, if you will.
This solution is definitely not ideal, because it just throws an exception if somebody tries assigning a value to driver that does not inherit from APerson, so no compile-time safety here.
But it's the best solution I could think of so far, if you really want to keep your interfaces separate and self-contained.
Related
I am faced with a C# design problem that C#'s limitations are making hard to achieve. I need some sort of design pattern/strategy to rescue me.
I must create the archetypical set of abstract shape classes: Base class Shape with derived classes LineShape, RectShape, etc. Specific implementations will derive from these. The problem is that I really need to use classes here, not interfaces and this is forcing me to duplicate a lot of code.
To illustrate:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
}
public abstract class LineShape : Shape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public abstract class CircleShape : Shape
{
public abstract Point Center { get; set; }
public abstract double Radius { get; set; }
}
When I start creating the derived implementations (LineImpl, CircleImpl, etc), I find that the implementations of the Shape functions are identical for all the Impl classes, yet specific enough that I cannot implement them in the abstract Shape class itself.
So I need to find a way to share a common implementation of these function in my derived hierarchy.
In other words LineImpl must derive from LineShape. CircleImpl must derive from CircleShape, etc. I cannot find a way to insert a ShapeImpl in there to handle the boiler plate stuff. So I am forced to implement all those Shape functions over and over again, once in each Impl shape type.
I tried using generics to get my way out of this but unfortunately a generic class cannot specify its base class with a generic argument. In other words, the following approach (which I might do in C++) does not work in C#
public class ShapeImpl<TBase> : T where T : Shape { ... boiler plate implemented here)...}
public class LineImpl : ShapeImpl<LineShape> { }
public class CircleImpl : ShapeImpl<CircleShape> { }
So I am at a loss. Is there some C# trick or design pattern that can get me out of this? Or am I forced to implement the same functions multiple times?
yet specific enough that I cannot implement them in the abstract Shape class itself.
You also mentioned:
I find that the implementations of the Shape functions are identical for all the Impl classes
I think that this is classic case of over-thinking for future implementation. if you say- the implementation is identical for all classes, I wouldn't bother too much over thinking for something in the future that may never arrive.
But, if you insist, you may implement it in the following way:
public abstract class Shape
{
public abstract int Id { get; } // Unique ID
public abstract string Name { get; set; } // Shape name. Defaults to the type of shape
public abstract bool IsLocked { get; set; } // May the user change this shape in any way?
public abstract void Foo();
}
public abstract class SepcificShape : Shape
{
protected virtual void FooSpecific()
{
Console.WriteLine("Specific Implementation");
}
}
public abstract class LineShape : SepcificShape
{
public abstract Point P1 { get; set; }
public abstract Point P2 { get; set; }
}
public class LineImp : SepcificShape
{
public override int Id { get; }
public override string Name { get; set; }
public override bool IsLocked { get; set; }
public override void Foo()
{
base.FooSpecific();
}
}
The only way to achieve something similar to multiple inheritance in C# I can think of would be to use default interface implementations, e.g. like this:
interface IShapeSdk
{
string GetNameSdk() => "Shape SDK name";
}
abstract class Shape
{
public abstract string GetName();
}
class ShapeImpl : Shape, IShapeSdk
{
public override string GetName()
{
return ((IShapeSdk)this).GetNameSdk();
}
}
This way all shapes will inherit from Shape, but only the external-SDK-shapes will inherit the common logic defined in IShapeSdk.
Not the cleanest approach, and a lot of C# developers are against the usage of this relatively new feature (which by the way is available only in C# 8 and above and .NET Core 3.0 and above).
I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
public enum Category { Mental, Physical, Technical }
interface IAbilities
{
List<IAbility> Abilities { get; set; }
}
interface IAbility
{
Category Category { get; }
int Value { get; set; }
string Descritpion { get; set; }
}
public class MentalAbilities : IAbilities
{
// This is what I want so that "Abilities" is accessible
public List<MentalAbility> Abilities { get; set; }
// This is what Intellisense generates, cannot be set to public
//List<IAbility> IAbilities.Abilities { get; set; }
}
public class MentalAbility : IAbility
{
public Category Category { get; } category
public int Value { get; set; }
public string Descritpion { get; set; }
}
Of course the Intellisense generated bit compiles, but "Abilities" is not accessible from a class instance because it can't be set to public.
The bit I want tells me `'MentalAbilities' does not implement interface member 'IAbilities.Abilities'. 'MentalAbilities.Abilities' cannot implement 'IAbilities.Abilities' because it does not have the matching return type of List<IAbility>.
I don't understand since "MentalAbility" is derived from the "IAbility" interface so that should fulfill the contract.
(I'm skipping over the "x is less accessible than y" error because you already worked out you can make your interfaces public - sure you can appreciate how anything has to be at least as accessible as it's use)
Re your "does not implement" error:
I understand your problem, but you've kinda got it upside down
I see that you want to ensure, in your MentalAbilities.Abilities list, someone only puts MentalAbility objects.. and they implement IAbility so it should satisfy the "object is a IAbilities and has a list which contains only things that implement IAbility" rules, right?
Alas, no. This the pretty much the opposite of what inheritance or interface implementation is for.
The idea behind inheritance is that you can say "this thing can be any type at all as long as it has these common aspects and I will treat it in the common way". By declaring such that List<IAbility> you're saying "objects in this list just have to implement IAbility and then I'll be able to deal with them" - it could be a MentalAbility, or a PhysicalAbility - doesn't matter
You cannot then constrain the list to only containing MentalAbility via the inheritance/implements mechanism, nor should you because it's opposite of what it is for- going from "I can deal with anything so long as it implements X" to "I will only deal with something if it is, or is a subtype of, Y" is the opposite of what was claimed earlier. You're saying that MentalAbilities can only deal with the list contents if they're MentalAbility, when you earlier said it could deal with anything that was an IAbility
If you want to enforce that MentalAbilities only contains MentalAbility you'll have to declare it as List<IAbility> and look at the type of the IAbility you're given in the set and refuse to add it if if it's not a MentalAbility, but if other developers use your code they will be very confused - "what? It says I'm allowed to use anything that implements IAbility, and my TigerAbility does just that.. why am I getting an exception that it must be a MentalAbility? Why did this developer even use a List(IAbility) if I'm not allowed to sling any IAbility I like into it?" - it's also no longer a compile time thing, but a runtime one and that's a big risk
I think you need to decide if you're going to be able to treat these things in a generic way i.e. can your AbilitiesProcessor implement IAbilities and have a list of IAbility and process them regardless of actual type, or not. If it can't, and you're going to have a MentalAbilities class that can only deal with MentalAbility that's fine, and it can have a List<MentalAbility> all it wants, fellow developers won't mistakenly put a TigerAbility into it, but it won't implement the IAbilities interface
I'm trying to get a simple set of interfaces to be nested so I can enforce some members on derived classes.
Your main issue here is that defined the two interfaces as private by default. That's what is preventing you from creating public List<IAbility> Abilities { get; set; } inside MentalAbilities.
Actually, the property public List<MentalAbility> Abilities { get; set; } is also preventing you as you can't have a property of the same name defined twice.
The big question here would be what would be the point of allowing MentalAbilities the ability to set a List<IAbility> since that would mean setting any type of ability.
Ideally MentalAbilities should only have a single list of MentalAbility that it contains - and it should only be read-only. In fact, most of your interfaces should be read-only.
Here's what you should do:
Start with these interfaces:
public interface IAbilities<A> where A : IAbility
{
List<A> Abilities { get; }
}
public interface IAbility
{
Category Category { get; }
int Value { get; }
string Description { get; }
}
Notice the IAbilities<A> interface uses a generic type A that you can fill in later.
Next, let's set up some base classes that simplify the implementation of each specific class.
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
}
public abstract class AbilityBase : IAbility
{
public abstract Category Category { get; }
public abstract int Value { get; }
public abstract string Description { get; }
}
Now the final classes are simple:
public class MentalAbilities : AbilitiesBase<MentalAbility> { }
public class MentalAbility : AbilityBase
{
public override Category Category => Category.Mental;
public override int Value => 42;
public override string Description => "Mental!";
}
There's nothing to implement in MentalAbilities - the base class took care of that - but it does have a List<MentalAbility> Abilities { get; } property.
MentalAbility is also neatly set up to enforce you to override the properties.
Now, if you actually wanted still have a List<IAbility> Abilities { get; } property then there's an easy way to do that by writing these two interfaces:
public interface IAbilities
{
List<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
This forces a change to AbilitiesBase like this:
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
List<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>().ToList();
}
The List<IAbility> IAbilities.Abilities property generates a copy of the public List<A> Abilities { get; protected set; } property, but that's what you want to prevent anyone adding the wrong type of ability to the original list.
Personally, I would go with this instead:
public interface IAbilities
{
IEnumerable<IAbility> Abilities { get; }
}
public interface IAbilities<A> : IAbilities where A : IAbility
{
new List<A> Abilities { get; }
}
public abstract class AbilitiesBase<A> : IAbilities<A> where A : IAbility
{
public List<A> Abilities { get; protected set; }
IEnumerable<IAbility> IAbilities.Abilities => this.Abilities.Cast<IAbility>();
}
What you are stuck with is called implicit and explicit implementation of interfaces in C#. If you define your class member like this:
public List<MentalAbility> Abilities { get; set; }
you are implementing IAbilities implicitly and you need to write public with it. If you define your class member as
List<IAbility> IAbilities.Abilities { get; set; }
you have implemented IAbilities explicitly, in which case it can be private.
While we are here, I see no point in defining an interface IAbilities. You should simply use IEnumerable<IAbility> anywhere you want to use IAbilities, which is literally providing no value in your code.
Why am I getting this error and how can I work around it when I CAN'T change the interfaces... (You can copy/paste the code into an empty CS file)
namespace ClassLibrary1
{
public interface IEntity
{
}
public interface IEntitySet<T>
{
}
public class Entity : IEntity
{
}
public class EntitySet<T> : IEntitySet<T>
{
}
public interface IImplementer
{
IEntitySet<IEntity> Set { get; set; }
}
public class Implementer : IImplementer
{
// Error 'ClassLibrary1.Implementer' does not implement interface member 'ClassLibrary1.IImplementer.Set'.
// 'ClassLibrary1.Implementer.Set' cannot implement 'ClassLibrary1.IImplementer.Set'
// because it does not have the matching return type of 'ClassLibrary1.IEntitySet<ClassLibrary1.IEntity>'.
public EntitySet<Entity> Set { get; set; }
}
}
Indeed, your Set method is meant to have a return type of IEntitySet<IEntity>, but you've tried to declare the implementation using EntitySet<Entity>. Two problems there:
IEntitySet isn't EntitySet
IEntity isn't Entity
The implementation signature has to match the interface exactly.
You should probably make IImplementer generic, like this:
public interface IImplementer<T> where T : IEntity
{
IEntitySet<T> Set { get; set; }
}
At that point, you can have:
public class Implementer : IImplementer<Entity>
{
public IEntitySet<Entity> Set { get; set; }
}
You can then write:
var implementer = new Implementer();
implementer.Set = new EntitySet<Entity>();
Is that what you want? If you really need to force Implementer to use EntitySet rather than just any IEntitySet, then you're probably coupling the two ideas too tightly.
You are getting this exception because IImplementer requires an IEntitySet<IEntity> Set property, but your Implementer class is returning an EntitySet<Entity>. EntitySet can be cast to IEntitySet, but IEntitySet cannot be cast to EntitySet, and so the interface implementation fails because you do not satisfy the interface.
Just change public EntitySet<Entity> Set {get; set;} to public IEntitySet<IEntity> Set {get; set;} on your Implementer class.
This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
I also showed using a base restriction class here, but it is not required.
The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables). In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object.
So indeed, having a list of IRestriction is the only sensible way to go.
As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int>. What I would do in this case is to define another property object Limit { get; } on IRestriction, and hide it in the actual implementation. Like this:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
This way you can access Limit as object on all your IRestriction when you don't care what type it is. For example:
foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.
The second interface seems to be restrictable objects that also contain a limit property.
Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.
Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
I m writing interfaces for new project and would like to get some advice.
I have a class that have a subclass and it has a subclass. The tree of this classes is like this:
Class Car
{
Wheels Wheel;
}
Class Wheels
{
Rims Rim;
}
So to simplify: one car has one wheel and one wheel has one rim. (cant make up other better example, sorry).
So I would like to force this hierarchy in my interface implementation of ICar, IWheels and IRims.
So i did something like this (in C#):
ICar
{
IWheels Wheel;
}
IWheels
{
IRims Rim;
}
And i have a error that I can not have fields in interface implementation. So this started me thing that maybe it's wrong interface design. I would like to force interface implementations to implement this kind of hierarchy. But maybe accorting to design patterns and best practices it should be done in other way?
Could you please tell me how to design my system so that objects will be forced to implement this kind of hierarchy?
Maybe there is something not precise in my question or I missing some important info. If yes, please ask in comments.
In your interface, you'll have to make it clear that Wheels should be a property of ICar, since you cannot declare which fields an interface implementation should have. (Fields are inner workings, so the interface should not know about it).
interface ICar
{
IWheels Wheels
{
get;
}
}
You can't specify a field in an interface (and you shouldn't be able to - that's an implementation decision) but you can specify a property:
public interface ICar
{
IWheels Wheel { get; set; }
}
public interface IWheels
{
IRims Rim { get; set; }
}
You may well want to only put the getter in the interface though - it's slightly unusual to include a setter in an interface:
public interface ICar
{
IWheels Wheel { get; }
}
public interface IWheels
{
IRims Rim { get; }
}
(There are oddities if you want to override an existing (or abstract) property which only has a getter to add a setter, but it's okay to implement a "getter-only" interface with setters as well, I believe.)
You can't declare fields, but you can declare properties. That will have the same end effect of forcing a particular class to provide an instance of another class.
ICar
{
IWheels Wheel { get; set; }
}
IWheels
{
IRims Rim { get; set; }
}
As the error says, you can't specify fields in your interfaces. You can specify properties though:
interface ICar
{
IWheels Wheel { get; set; }
}
interface IWheels
{
IRims Rim { get; set; }
}
I'm not so much used to C# but it sounds to me that you can force that implementation by making Abstract classes, with the fields you want to use.
So if you extend those abstract classes you will have the fields in them available.
You'll have to make an abstract class AND an interface though...
Here it is a fully functional code...
Hope it helps...
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication10
{
//Interfaces
public interface ICar
{
string name { get;}
IWheel wheel { get;}
}
public interface IWheel
{
string brand { get;}
}
//Implementations
public class Michelin : IWheel
{
#region IWheel Members
public string brand
{
get { return "michelin"; }
}
#endregion
}
public class Toyota : ICar
{
Michelin m = new Michelin();
#region ICar Members
public string name
{
get { return "toyota"; }
}
public IWheel wheel
{
get { return m; }
}
#endregion
}
//A user of the interfaces. Only cares about ICar but knows implicitly about IWheel
public class Stand
{
public Stand()
{
cars = new List<ICar>(2);
cars.Add(new Toyota());
cars.Add(new Toyota());
}
List<ICar> cars;
public string ShowCars()
{
StringBuilder str = new StringBuilder();
foreach (ICar iterCar in cars)
{
str.AppendLine(string.Format("car {0} with wheel {1}",
iterCar.name, iterCar.wheel.brand));
}
return str.ToString();
}
}
//entry point. creates a stand and shows the cars, testing that properties are visible
class Program
{
static void Main(string[] args)
{
Stand myLittleStand = new Stand();
Console.WriteLine(myLittleStand.ShowCars());
}
}
}