Reputation: 1901
I want to have 2 very similar classes that will have some common behavior, but different properties, so I need to make these two classes Invoice
and CreditNote
to be under "one generic object" in this case called model
I was thinking to implement a inteface which will be having input object type like:
public interface IInvoice<T>
{
T InvoiceType { get; set; }
}
But Im not quite sure if this is the way for this.
Ultimately, I would like instancing these classes from interface: IInvoice = new Invoice();
Here is an example:
//380-invoice
if(Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.Invoice.Id)
{
Invoice model = new Invoice();
model.RequestId = request.CorrelationId;
model.SendToCir = "Auto";
}
//383-creditNote
if (Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.CreditNote.Id)
{
CreditNote model = JsonConvert.DeserializeObject<CreditNote>(request.Content)!;
model.RequestId = request.CorrelationId;
model.SendToCir = "Auto";
}
model.Name = "foo"; // not accesible
Upvotes: 0
Views: 204
Reputation: 656
Interface seems like the right answer for what you're trying to accomplish. Read up some more on interfaces and polymorphism to fully understand their usage.
Interfaces are correct for you if...
You want any class working with your IInvoice
objects to be completely blind to whether the object it's handling an Invoice
or CreditNote
save for the brief moment when your objects are created.
It looks like you're 90% of the way there, the one thing it seems you're missing is that interfaces are not "instantiated", classes are. so you can have the following method:
public IInvoice CreateInvoice(Request request, int invoiceType)
{
//380-invoice
if(Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.Invoice.Id)
{
Invoice model = new Invoice();
model.RequestId = request.CorrelationId;
model.SendToCir = "Auto";
return model;
}
//383-creditNote
if (Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.CreditNote.Id)
{
CreditNote model = JsonConvert.DeserializeObject<CreditNote> (request.Content)!;
model.RequestId = request.CorrelationId;
model.SendToCir = "Auto";
return model;
}
throw new NotImplementedException($"Unexpected invoice type {invoiceType}");
}
and then anywhere in your code you can use
IInvoice myInvoice = CreateInvoice(request, invType);
the only members of myInvoice
you'll be able to access are the ones defined on the interface IInvoice
. If you want to access the Name
property, you'll need to either add it to the IInvoice
interface and implement it on both Invoice
and CreditNote
or you can down-cast your myInvoice
object into a concrete type which has the Name
property exposed. I don't recommend this approach since the whole point of polymorphism is to remove concrete understanding of the underlying implementation.
Edit: after thinking about your comment I think I understand what you want, let me know if the following makes sense.
You can make just the one model like so:
public class InvoiceMode
{
public long RequestId{get;set;}
public string SendToCir {get;set;}
public string Name{get;set;}
... etc
}
and then in your code you can have the following:
public InvoiceModel CreateInvoice(Request request, int invoiceType)
{
InvoiceModel model;
//380-invoice
if(Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.Invoice.Id)
{
model = new Invoice();
}
//383-creditNote
else if (Convert.ToInt32(invoiceType) == InvoiceTypeCodeEnumDto.CreditNote.Id)
{
model = JsonConvert.DeserializeObject<CreditNote> (request.Content)!;
}
// Unknown invoice type -- throw error
else
{
throw new NotImplementedException($"Unexpected invoice type {invoiceType}");
}
model.RequestId = request.CorrelationId;
model.SendToCir = "Auto";
return model;
}
Upvotes: 1