Problem implementing generic interface - c#

I have a base DLL which defines some basic structure and operation for a key concept within our business. This dll is then included in specific web services for each vendor that implement the specific business rules for interacting with that vendor. (While the basic concepts are the same the implementations are very different and can change independently.)
In the base dll I have a series of interfaces set up as such
public interface IVendor
{
string Name { get; set; }
}
public interface IVendor<TC> : IVendor where TC : IAccount
{
IEnumerable<TC> Accounts { get; set; }
}
public interface IAccount
{
string Name { get; set; }
}
public interface IAccount<TP, TC> : IAccount where TP : IVendor
where TC : IExecutionPeriod
{
TP Vendor{ get; set; }
IEnumerable<TC> ExecutionPeriods { get; set; }
}
This continues down several more tiers, and everything compiles fine.
The problem comes when I try to implement this down in the service.
public class FirstVendor : IVendor<FirstVendorAccount>
{
public string Name { get; set; }
public IEnumerable<FirstVendorAccount> Accounts { get; set;}
}
public class FirstVendorAccount : IAccount<FirstVendor, FirstVendorExecutionPeriod>
{
public FirstVendor Vendor { get; set; }
public string Name { get; set; }
public IEnumerable<FirstVendorExecutionPeriod> ExecutionPeriods { get; set; }
}
I get a compiler error that IVendor, IAccount, etc. do not have type parameters. Which is particularly odd because when I asked it to implement the interface it included all of the members from both relevant interfaces.

It looks like you have a circular reference - FirstVendorAccount needs to know about FirstVendor before it can compile and vice versa.
Make one of these the 'dominant' class with the generic type, then the other can just return the base interface.
For instance:
public interface IVendor
{
string Name { get; set; }
}
public interface IVendor<TC> : IVendor where TC : IAccount
{
IEnumerable<TC> Accounts { get; set; }
}
public interface IAccount
{
string Name { get; set; }
}
// no longer needs IVendor<TC> before it can be compiled
public interface IAccount<TC> : IAccount where TC : IExecutionPeriod
{
IVendor Vendor{ get; set; }
IEnumerable<TC> ExecutionPeriods { get; set; }
}
It's worth looking at whether you really need all the generic typing - you may be better off with the non-generic underlying interfaces as these will be much easier to code with.

Related

How to handle class inheritance in LiteDB with custom IDs

I would like to persist a class which implements an interface and can have various subclasses. I am just trying to understand how LiteDB handles this setup.
In particular I have a code structure like so:
public interface IItem
{
string UniqueKey { get; set;
string OtherProperties { get; set; }
}
public class Item : IItem
{
public string UniqueKey { get; set; }
public string OtherProperties { get; set; }
}
public class ItemOne : Item
{
public string ItemOneProperty { get; set; }
}
public class ItemTwo : Item
{
public string ItemTwoProperty { get; set; }
}
public class Main
{
public void Init()
{
// Can this apply to all interface implementations?
BsonMapper.Global.Entity<IItem>().Id(oid => oid.UniqueKey);
// This will apply to Item but not ItemOne or ItemTwo
BsonMapper.Global.Entity<Item>().Id(oid => oid.UniqueKey);
}
}
For reasons of wanting to keep the class structure clean, I do not want to use [BsonId] on the key. This means I need to use the BsonMapper to declare the ID. However, it looks like even though the mapper defines the ID on the base interface, it does not apply to any of the concrete classes.
Ideally, I do not want to declare the ID for every subclass in BsonMapper as - aside from there being many subclasses - it would create an unwanted dependency.
Does anyone know the best approach to solve this issue?

Using abstract class property in interface in C# [duplicate]

This question already has answers here:
C#: Interface to force list of items inheriting the interface
(3 answers)
Closed 10 months ago.
I am trying to deal with a problem of with interfaces and implementations. See code below.
public interface IMachine
{
string Name { get; set; }
List<IElement> Elements { get; set; }
List<IWire> Wires { get; set; }
}
public class ElementA : IElement { }
public class ElementB : IElement { }
public class WireA : IWire { }
public class WireB : IWire { }
public class MachineA : IMachine
{
public List<ElementA> Elements { get; set; }
public List<WireA> Wires { get; set; }
}
public class MachineB : IMachine
{
public List<ElementB> Elements { get; set; }
public List<WireB> Wires{ get; set; }
}
What I want to do in my program, is to iterate over IMachine elements stored in a list, and then access all Wire and Element members, without taking too much care about the exact type.
Is this even possible? I did some experiments with abstract classes, casting, but I'm stuck.
Well, of course code above will not compile as I get error, that I am missing implementation of interface member.
A/B classes vary in details (basic properties are same, but I use some specific ones for each class), so casting does not work, too.
Your fundamental problem is that a List<WireA> is not a List<IWire>, so you are not fulfilling the interface contract. If you want to access the lists as list of a specific type (rather than List<IElement>, for example) and avoid casting the elements, you could use generics:
public interface IMachine<TElement, TWire> where TElement : IElement, TWire : IWire
{
string Name { get; set; }
List<TElement> Elements { get; set; }
List<TWire> Wires { get; set; }
}
public class MachineA : IMachine<ElementA, WireA>
{
public List<ElementA> Elements { get; set; }
public List<WireA> Wires { get; set; }
}
public class MachineB : IMachine<ElementB, WireB>
{
public List<ElementB> Elements { get; set; }
public List<WireB> Wires{ get; set; }
}
Suppose your IWire required the implementation of GetName() and there existed at least one IWire object in your Wires collection then the code would return whatever was implemented by the instance of IWire's GetName() method.
var machines = new List<IMachine>();
machines.Add(new MachineA());
machines.Add(new MachineB());
machines.Add(new MachineA());
foreach(var machine in machines)
{
Console.WriteLine(machine.Wires[0].GetName());
}

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.

MEF dafault Import of base class

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

Extending Existing Interface Design

I have several classes which implement some interface, and instead of modifying it, I want to extend it with another interface.
When I'm thinking about designing the extending interface I'm not sure what is the best practice of how to include a reference to the original interface?
Id reference or include it as a property of the extending interface?
I've created an example below to show the need:
public interface IMovie
{
string UniqueId { get; set; }
string Name { get; set; }
string Ratnig { get; set; }
}
//Option #1
public interface IMovieWithSubTitles
{
string UniqueId { get; set; }
string SubTitles { get; set; }
}
//Option #2
public interface IMovieWithSubTitles
{
IMovie Movie { get; set; }
string SubTitles { get; set; }
}
Third option (inheritance):
interface IMovieWithSubTitles : IMovie
{
string SubTitles { get; set; }
}
Your first one just declares a separate interface. The second one aggregates IMovie. Both cases do not extend IMovie.
I would have inherited IMovie with the new interface, such as
public interface IMovieWithSubTitles : IMovie
{
string SubTitles { get; set; }
}

Categories

Resources