C# implement interface with properties that are interface. - c#

I am using EF code first to generate my db and I do need concrete property for ICollection of EF entity models. I am writing a data access layer ( Using generic classes) however hit the following road block with using interfaces in my generic class as shown below.
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass
{
ICollection<ITestClassProp> TestProp { get; set; }
}
public class TestClass : ITestClass
{
// works
//public ICollection<ITestClassProp> TestProp { get; set; }
// does not work
public ICollection<TestClassProp> TestProp { get; set; }
}
Am I totally mis using the interfaces? why cant I use TestClassProp instead of ITestClassProp?
Thanks

When you implement an interface, you have to implement the methods/properties of that interface with the same signature. Since the interface declares ICollection<ITestClassProp> TestProp { get; set; } then your TestClass must also declare ICollection<TestClassProp> TestProp { get; set; }.
The reason this is necessary is that other classes that know about the interface but not the concrete class are expecting the property to be ICollection<ITestClassProp> and not ICollection<TestClassProp>.

As you've currently written your code, you are not satisfying the requirement you've imposed via your ITestClass interface, which is to have a property of ICollection<ITestProp>.
One way around this is to actually make ITestClass generic, but provide a generic constraint of ITestClassProp
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass<T> where T : ITestClassProp
{
ICollection<T> TestProp { get; set; }
}
public class TestClass : ITestClass<TestClassProp>
{
public ICollection<TestClassProp> TestProp { get; set; }
}
This allows you to provide any concrete type that implements ITestProp to your ICollection.

Simply, the interface declares a property of type ICollection, but you implement it as ICollection, which has a totally different signature.
You might want to read up on covariance and contravariance also.

Related

How to suppress based-class property in favor of the same new derived-class property on model creating

I have a base class MyBaseClass, with a wrapper class MyWrapperClass which is derived from that base class. The purpose of declaring wrapper class is to detaching the EntityFramework-related annotations, Id properties and navigation properties from the base class. The structure of base class and derived class are as follows:
public class MyBaseClass
{
public ClassA MyProperty { get; set; }
}
public class MyWrapperClass: MyBaseClass
{
public int Id { get; set; }
public new ClassAWrapper MyProperty { get; set; }
}
I cannot use virtual...override pattern on MyProperty, because of the differet types for MyProperty in base class and derived class.
Thus, i put new keyword before MyProperty property, and i expect the EntityFramework to create the model based on ClassAWrapper instead of ClassA.
But i get an error when trying to add-migration: "ClassA should have a key". While ClassA has not a key property, but ClassAWrapper has.
DbContext implementation is as follows:
public class MyDbContext : DbContext
{
public DbSet<MyDerivedClass> MyDerivedClass { get; set; }
...
}
Problem: I need to tell the EntityFramework to give up on the MyProperty class of the base class (which is of type ClassA), and look at the same property in the derive class (with type ClassAWrapper) when creating the model.
Try NotMapped and Key data annotations, like this:
public class MyBaseClass
{
[NotMapped]
public ClassA MyProperty { get; set; }
}
public class MyWrapperClass: MyBaseClass
{
[Key]
public int Id { get; set; }
public new ClassAWrapper MyProperty { get; set; }
}

Overriding abstract list<a> property with list<A>

I'm writing a piece of code to make certain reports. There are 4 types of reports which the user can request. Each type report is based on the base class 'report'. Each derived class has a List. The class 'A' is derived from base class 'a'.
Is it possible to add an abstract List to the 'report' class and let it be overridden by a List in the derived report classes? Something like this?
public abstract class Report
{
public abstract List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
public override List<A> Coils { get; set; }
}
public class a
{
public string SomeProperty { get; set; }
}
public class A: a
{
public string SomeOtherProperty { get; set; }
}
I'm kind of new to C# so if I'm asking something really basic or I have a big flaw in my thinking, please do point it out. But please don't just answer with yes or no.
Based on your description of the usage, there is no need to override the List/collection in your new class. Since A inherits from a, you can store objects of type A in "Coils". (due to polymorphism). Then if, at some later time, you want to access "SomeOtherProperty" of the objects of type A, you could use a cast.
public abstract class Report
{
public List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
}
public class a
{
public string SomeProperty { get; set; }
}
public class A : a
{
public string SomeOtherProperty { get; set; }
}
public void SomeMethod()
{
//to store the coil
ProductionExitCoilReport myReport = new ProductionExitCoilReport();
myReport.Coils.Add(new A());
//to retreive SomeOtherProperty from the first element in the list
string retrievedProperty = ((A)myReport.Coils[0]).SomeOtherProperty;
}
Your properties are readable and writable.
Derived types must always be compatible with the base type.
Every Report has Coils property that returns a read/write collections of items of type a. Thus you can always write report.Coils.Add(new a()).
ProductionExitCoilReport inherits from Report, so it would have been possible to run the same code - to add a (not A) to the collection returned by Coils: ((Report)productionReport).Coils.Add(new a()).
This contradicts what you want to accomplish.
Please read about covariance and contravariance:

Implementing type constraint for an unassociated C# Class

I'm writing a C# application that will generate Dungeons & Dragons characters in bulk. However when I encountered the concept of a "bonus" to a character parameter I ran face first into a wall. Correctly constraining generic types for the method of the bonus escapes me. Here is an example of what I have:
public interface IAbilityScore : IBaseEntity
{
string Name { get; set; }
}
public interface IBonus<T,K> where T : IBonusable<K>
{
K Value { get; set; }
}
public interface IBonusable<T>
{
T Value { get; set; }
}
public interface ICharacterAbilityScore : IBaseEntity, IBonusable<int>
{
ICharacter Character { get; set; }
IAbilityScore AbilityScore { get; set; }
bool IsSaveProficient { get; set; }
}
The problem I face is that from a user perspective, I want the user to be able to add "This race gives a +2 bonus to Intelligence". Unfortunately, the ability score "Intelligence" won't have a Value property until it's associated with a character, thus making the IBonusable constraint an issue.
I would like to be able to constrain the value property of the IBonus to the same type as the value property of the IBonusable item without having to tie the bonus directly to a specific character (which would happen in my above implementation, with ICharacterAbilityScore inherting IBonusable).
Is there an interface-only method of accomplishing this, or will I have to add this constraint in when I define the concrete implementations?
Also, I plan on using code first EF to build out the database, if that affects the answer.
Am not sure if I understood your question correctly, but this per my understanding.
public interface IAbilityScore : IBaseEntity
{
string Name { get; set; }
}
public interface IBonus<T>
{
T Value { get; set; }
}
public interface IBonusable<T>
{
T Value { get; set; }
}
public interface ICharacterAbilityScore<T> : IBaseEntity, IBonusable<T>,IBonus<T>
{
ICharacter Character { get; set; }
IAbilityScore AbilityScore { get; set; }
bool IsSaveProficient { get; set; }
}

C#, abstract superclass implementing a concrete variable defined by the subclass?

I have a system that performs operations on lots of Things, these can be considered to be hardware devices accessible over a communication channel.
I use a manager construct that accepts tasks for single Things. Now, there are at least three types of Thing and they have slightly different properties associated with them. The manager must know about these extra properties as they are needed to perform any operation correctly (some Things must have their X foo'd instead of their Y etc...).
At the moment I have separate manager class for each type of thing. This causes a good deal of duplication as the Things are mostly similar.
It would be good if I could have an abstract manager that implements a good deal of the functionality and then each concrete implementation can supply the little extra bits.
Here is a greatly simplified example:
public abstract class ThingManager
{
private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;
public virtual AddNewThingTask(<params>)
{
??ThingTask?? NewTask = new ??ThingTask??(<params>);
_ThingTaskQueue.Add(NewTask);
Monitor.Pulse(_NewDataToProcess);
}
/* Implemented by the concrete, will depend on the type of ??ThingTask?? */
public abstract GetSomeTaskParameterForAThing(Guid thingID)
}
public class ThingTask
{
public enum ThingOperation
{
Foo,
Bar
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
}
public class AdvancedThingTask
{
public enum ThingOperation
{
Foo,
Bar,
Baz
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
public Boolean EnableFrobber { get; set; }
}
As you can see I need some way, when defining the concrete ThingManager to have ??ThingTask?? be either a ThingTask or an AdvancedThingTask. It would then be up to the concrete to make use of the extra properties when implementing the abstract methods.
Using an interface for ??ThingTask?? wouldn't work because the properties would have to be declared in the interface and each one has different properties available.
I get the feeling I'm missing something very obvious as to how to do this cleanly, hopefully someone can help :)
use generics rather than a pure abstract class, someting along the lines of:
public abstract class ThingManager<T> where T : ThingTask
dependant on your full implementation I doubt if this will need to remain abstract
Is there any reason you don't make AdvancedThingTask a subclass of ThingTask?
public class ThingTask
{
public virtual string Name { get; set; }
public virtual ThingType Type { get; set; }
public virtual ThingOperation Operation { get; set; }
public virtual void DoThing() { /*Do something associated with ThingTask*/ }
}
public class AdvancedThingTask : ThingTask
{
public bool EnableFrobber { get; set; }
public override void DoThing() { /*Do something associated with AdvancedThingTask*/ }
}
The only problem I see with this is that ThingOperation will need to be declared outside of the classes so that it can have all the values, or some other solution that will enable classes to have values that aren't in the base declaration. That problem may be solved by putting what you want to do as virtual methods in the classes.
P.S. Why do your properties start with underscores? Usually that's reserved for private variables.

Trouble defining an IList<T> where T is an generic interface

I am attempting to declare and use an interface like this:
public interface IItem<T>
{
string Name { get; set; }
T Value { get; set; }
}
This works fine until I attempt to create a list of these items. This fails to compile:
public interface IThing
{
string Name { get; }
IList<IItem<T>> ThingItems { get; }
}
so I am not certain where the issue is. The items value is not defined until runtime, and I need to have collections of the items. I figure that this is a fairly standard pattern, but I can not see where I am falling down.
Your class needs to be generic too (Thing<T>) or else the list can't know what type to use.
public interface Thing<T>
{
string Name { get; }
IList<IItem<T>> thingItems { get; }
}
EDIT
It compiles now.
EDIT
It seems you want your IItem<T> to be in terms of any type. This won't work in C#. You could create IList> here, but that is less than ideal, since you loose your typing when you want to get the items out.
You're falling down because the compiler wants to know what kind of items are in your list. So if you don't know yet, just create a non-generic base interface, and derive a generic more specific interface:
Maybe this helps you out:
public interface IItem
{
string Name { get; set; }
}
public interface IItem<T>: IItem
{
T Value { get; set; }
}
public interface IThing
{
string Name { get; }
IList<IItem> Items { get; }
}
public interface IThing<T>: IThing
{
string Name { get; }
IList<IItem<T>> Items { get; }
}
Interfaces cannot contain fields (data members)
A type containing a generic type is also a generic type
Two problems:
You can't declare fields in an interface. (rationale: a field is considered an implementation detail, which is the thing interfaces are designed to abstract away)
You can't have a generic field without specifying the type parameter (unless you have a type parameter on the declaring type too).
When you create an instace of Thing you have to know what the type of Thing.thingItems is. So the following is the correct way.
public interface Thing<T>
{
String Name { get; }
IList<IItem<T>> thingItems { get; }
}
If you do not know the concret type at the point of instanciating Thing you can only use a common base class or a common interface for the type.
public interface Thing<T>
{
String Name { get; }
IList<IItem<ThingParameterBase>> thingItems { get; }
}
Or with a common interface.
public interface Thing<T>
{
String Name { get; }
IList<IItem<IThingParameter>> thingItems { get; }
}

Categories