How to impliment an implement which has an interface property? - c#

I'm wanting a class to have a property that is another class, but i want both the outside and inside classes to implement an interface, the outside interface having a property for the one on the inside.
Here's the code I've tried.
interface IMainBody
{
ISubProperty subProperty { get; set; }
}
interface ISubProperty
{
string somethingHere { get; set; }
}
class MainBody : IMainBody // Error CS0738 'MainBody' does not implement interface member 'IMainBody.subProperty'. 'MainBody.subProperty' cannot implement 'IMainBody.subProperty' because it does not have the matching return type of 'ISubProperty'.
{
public SubProperty subProperty { get; set; }
}
class SubProperty : ISubProperty
{
public string somethingHere { get; set; }
}
I know I could use a generic interface like this
interface IMainBody<T>
where T : ISubProperty
{
T subProperty { get; set; }
}
interface ISubProperty
{
string somethingHere { get; set; }
}
But I would prefer not to do this because it means the code will get very messy once there is more than one property like this.
Anyone know of any other workarounds?

class MainBody : IMainBody
{
public SubProperty subProperty { get; set; }
ISubProperty IMainBody.subProperty { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}

Related

C# Interface Inheritance override

I confused about a base interface property hiding, what is still needed in the implemented class, can somebody tell me why?
The goal will be the 'EndClass' only hide/override the 'IClassValue Value', and not need to implement the already hide 'IBaseClassValue Value'.
Thanks!
public interface IBaseClassValue { }
public interface IClassValue : IBaseClassValue { }
public class ClassValue : IClassValue { }
//-----------------------------------------
public interface IEndClassBase
{
IBaseClassValue Value { get; set; }
}
public interface IEndClassBaseChild : IEndClassBase
{
new IClassValue Value { get; set; }
}
//-----------------------------------------
public abstract class EndClassAbs<TValue>
{
TValue Value { get; set; }
}
public class EndClass : EndClassAbs<ClassValue>, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
//IBaseClassValue IEndClassBase.Value { get; set; } //-> Why need here the base member while already hide in the 'IEndClassBaseChild' interface
}
If I use somekind of shadow class '_EndClass' then inherit from it, the 'EndClass' could hide/override the 'ClassValue'. I still don't know why this can not do in one step.
public class _EndClass : EndClassAbs<ClassValue>, IEndClassBase
{
public new IBaseClassValue Value { get; set; }
}
public class EndClass : _EndClass, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
}

removing an item from an interface based collection will not work

(FYI, Foo and Bar are Entity Framework POCO entity classes)
I would like to use this interface:
public interface IFoo
{
int Id { get; set; }
string Name { get; set; }
ICollection<IBar> IBars{ get; set; } //association with another entity
}
My implementation is as follows:
public class Foo : IFoo
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Bar> Bars{ get; set; }
//Interface implementation
public ICollection<IBar> IBars
{
get
{
return Bars.Cast<IBar>().ToList();
//or return new List<ICardInquiry>(CardsInquiries);
}
set
{
if (value is ICollection<IBar>)
Bars= ((ICollection<IBar>)value).Cast<Bar>().ToList();
else
throw new NotImplementedException();
}
}
}
This implementation prevents me to remove an element from the collection:
IFoo iFoo = MyIFooFactory.CreateIFoo();
IBar iBar = iFooIBars.First();
iFoo.IBars.Remove(iBar);
This will NOT remove the element! I do understand why. The reason is my interface collection getter, which is again as follows:
public ICollection<IBar> IBars
{
get
{
return Bars.Cast<IBar>().ToList();
//or return new List<ICardInquiry>(CardsInquiries);
}
...
}
IBars returns a new list so the element is removed from the returned list and not from the original collection (Bars).
How can I get out of this situation? I really don't want IFoo to know about Bar and to only manimpulate IBar.

Interface Cannot implicitly convert type

I have following code below. I have two main interfaces IWatch and IWatchService. Oryginally Watch() was in IWatchService and there was no IWatch but since that CollectionService cannot use Watch() method i decided (ISP) to create IWatch interface additionally.In CollectionService i want in ctor pass either DatabaseWatchService or RemoteFilesWatchService therefore i put parameter type in ctor as IWatchService<IEntity> watchService nevertheless when in DoIt() method initialize fileWatcherServiceCsv variable it says:
Cannot implicitly convert type 'RemoteFilesWatchService' to
'IWatchService'. An explicit conversion exists (are you
missing a cast?)
public interface IWatch
{
void Watch();
}
public interface IWatchService<TDataEntity> where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
ObservableCollection<TDataEntity> MatchingEntries { get; set; }
}
public interface IDatabaseWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IDatabaseEntity
{
IDatabaseRepository<IDbManager> DatabaseRepository { get; }
}
public interface IRemoteFilesWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IFileEntity
{
List<string> ExistingRemoteFiles { get; set; }
List<RemoteLocation> RemoteLocations { get; set; }
IWinScpOperations RemoteManager { get; set; }
IRemoteFilesRepository<IDbManager, TDataEntity> RemoteFilesRepository { get; }
}
public class RemoteFilesWatchService : IRemoteFilesWatchService<IFileEntity>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<IFileEntity> MatchingEntries { get; set; }
public List<string> ExistingRemoteFiles { get; set; }
public List<RemoteLocation> RemoteLocations { get; set; }
public IWinScpOperations RemoteManager { get; set; }
public IRemoteFilesRepository<IDbManager, IFileEntity> RemoteFilesRepository { get; }
public RemoteFilesWatchService(IWinScpOperations remoteOperator,
IRemoteFilesRepository<IDbManager, IFileEntity> remoteFilesRepository,
INotificationFactory notificationFactory)
{
RemoteManager = remoteOperator;
RemoteFilesRepository = remoteFilesRepository; //csv, xml or other repo could be injected
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class DatabaseWatchService : IDatabaseWatchService<DatabaseQuery>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<DatabaseQuery> MatchingEntries { get; set; }
public IDatabaseRepository<IDbManager> DatabaseRepository { get; }
public DatabaseWatchService(IDatabaseRepository<IDbManager> databaseRepository,
INotificationFactory notificationFactory)
{
DatabaseRepository = databaseRepository;
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class CollectionService
{
private IWatchService<IEntity> _watchService;
public CollectionService(IWatchService<IEntity> watchService)
{
_watchService = watchService;
}
}
class Run
{
void DoIt()
{
IWatchService<IEntity> fileWatcherServiceCsv = new RemoteFilesWatchService(new WinScpOperations(),
new RemoteCsvFilesRepository(new DbManager(ConnectionDbType.MySql)),
new NotificationFactory());
var coll1 = new CollectionService(fileWatcherServiceCsv);
}
}
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
int Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
bool RemoveFromSource { get; set; }
string DestinationFolder { get; set; }
RemoteLocation RemoteLocation { get; set; }
}
public interface IDatabaseEntity : IEntity
{
}
public class CsvFile : IFileEntity
{
public int ColumnHeader { get; set; }
public int ColumnsCount { get; set; }
public string Separator { get; set; }
public int ValuesRowStartposition { get; set; }
public int ColumnRowPosition { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
}
public class XmlFile : IFileEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
public string SubNode { get; set; }
public string MainNode { get; set; }
}
This question gets posted almost every day. One more time!
A box of apples is not a box of fruit. Why not?
You can put a banana into a box of fruit, but you cannot put a banana into a box of apples, so a box of apples is not a box of fruit, because the operations you can perform on them are different. Similarly, a box of fruit is not a box of apples.
You're trying to use a IWatchService (box) of IFileEntity (apples) as an IWatchService of IEntity (fruit), and that's not legal.
Now, you might notice that in C# you can use an IEnumerable<Apple> where an IEnumerable<Fruit> is expected. That works just fine because there is no way to put a banana into an IEnumerable<Fruit>. In every member of IEnumerable<T> and IEnumerator<T>, the T comes out, not in.
If you are in that situation then you can mark your interface as
interface IWatchService<out T> ...
And the compiler will verify that every T in the interface is used in "out" positions, and then will allow the conversion you want.
That conversion is called a generic covariant conversion and it only works when:
The generic type is an interface or delegate
The type parameter is marked out, and the compiler verifies that is safe
The varying types (Fruit and Apple, say) are both reference types. You can't do covariant conversions involving int and object, for example.
Your RemoteFilesWatchService implements interface IWatchService<IFileEntity>, while your CollectionService expects a IWatchService<IEntity>. The two types are different, that's why it cannot convert.
Modify your CollectionService to accept IWatchService<IFileEntity> instead, or make RemoteFilesWatchService implement IRemoteFilesWatchService<IEntity>. Or use a non-generic interface in CollectionService instead.
You cannot have a IWatchService<IFileEntity> and treat it as a IWatchService<IEntity>. Compare it to a List<T> for example. You cannot expect to be able to do this:
class Animal {}
class Bird : Animal {}
class Elephant : Animal {}
var birds = new List<Bird>();
// compiler does not allow this...
List<Animal> animals = birds;
// ...because there is no point in adding elephants to a list of birds.
animals.Add(new Elephant());
Making a slight change to take support from variance, should fix your issue as follows:
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
...
}
public interface IWatchService<out TDataEntity> where TDataEntity : IEntity //note the "out" keyword here.
{
}
You can learn more about Variance in Generic Interfaces Here

Specialize type when hiding property in subclass c#

i need an help on a really easy question about oop .net design.
I've an abstracted class:
public abstract class DataExtractionMethodConfig
{
public abstract DataExtractionMethod DataExtractionMethod { get; }
public object DataExtractionConfig { get; protected set; }
}
where DataExtractionConfig is a simple object that will be used in subclass to contains the configuration details. For example the OdbcExtractionConfig will be
public class OdbcExtractionConfig
{
public string OdbcName { get; set; }
public string BarcodeFilterExpression { get; set; }
public string ConnectionString { get; set; }
public string SqlCommand { get; set; }
public Enum.DatabaseServer DatabaseType { get; set; }
public List<string> KeyColumns { get; set; }
}
and the derived concrete class is
public class OdbcDataExtractionMethod : DataExtractionMethodConfig
{
private OdbcDataExtractionMethod(){}
public OdbcDataExtractionMethod(OdbcExtractionConfig config)
{
this.DataExtractionConfig = config;
}
public override DataExtractionMethod DataExtractionMethod { get { return DataExtractionMethod.ODBC; } }
}
How can i refactor the code to have DataExtractionConfig typed and not a simple object but mantaining the capability to extend the abstract class ?
How can i refactor the code to have DataExtractionConfig typed and not a simple object
By using Generics, but I warn you it can sometimes be a rabbit hole! Meaning that once you start down it, you get deeper and deeper, and things get more and more complex as you go.
public abstract class DataExtractionMethodConfig<T>
{
public abstract DataExtractionMethod DataExtractionMethod { get; }
public T DataExtractionConfig { get; protected set; }
}
And then
public class OdbcDataExtractionMethod : DataExtractionMethodConfig<OdbcExtractionConfig>
{ ... }

Confused about interfaces and implementation

The case is very simple, I have this interface
public interface IHasNext
{
IHasNext NextItem { get; set; }
}
and then I attempt to implement it like so:
public class Item : IHasNext
{
public int Id { get; set; }
Item NextItem { get; set; }
}
but this won't work because the property NextItem of the implementation is not of the same type (even if the type implements the interface). So could someone kindly explain me the reason for this not working, when you can quite liberally swap types for interfaces they implement even as type parameters (at least on IEnumerable and IQueryable).
Consider this code:
public class BadItem : IHasNext
{
public IHasNext { get; set; }
}
Now:
IHasNext item = new Item();
item.NextItem = new BadItem();
That's perfectly valid... but what would you expect it to do on the Item class? Its NextItem property is of type Item, so it doesn't know what to do with a BadItem...
Basically, doing this is unsafe.
You may want to make your interface generic:
public interface IHasNext<T> where T : IHasNext<T>
{
T NextItem { get; set; }
}
public class Item : IHasNext<Item>
{
public int Id { get; set; }
IHasNext<Item> NextItem { get; set; }
}
The interface states that the property must be of type IHasNext, your code should be:
public class Item : IHasNext
{
public int Id { get; set; }
IHasNext NextItem { get; set; }
}
Why aren't you implementing it as:
public class Item : IHasNext
{
public int Id { get; set; }
IHasNext NextItem { get; set; }
}
? This interface could be on any class that implements IHasNext.
But better still is to make it generic
public interface IHasNext<T>
{
T NextItem { get; set; }
}
public class Item : IHasNext<Item>
{
public int Id { get; set; }
Item NextItem { get; set; }
}

Categories

Resources