0

I have one request interface IRequest and two classes ClientAddress and ClientOrder are implementing it. The same design is followed for Response with inteface IResponse and classes ClientAddressResponse and ClientOrderResponse.

I have tried to do it 2 ways but I am not sure which is better way

  1. With Explicit type casting by assigning class object to interface.
  2. By using classes object and variable

See here:

public interface IRequest
{
    string ClientId { get; set; }
}

public class ClientAddress : IRequest
{
    public string ClientId { get; set; }
    public string AppId { get; set; }
}

public class ClientOrder : IRequest
{
    public string ClientId { get; set; }
    public string FromDate { get; set; }
    public string ToDate { get; set; }
    //other properties
}

public interface IResponse
{
    string ClientName { get; set; }
}

public class ClientAddressResponse : IResponse
{
    public string ClientName { get; set; }
    public string HouseNumber { get; set; }
    public string Area { get; set; }
    public string City { get; set; }
}

public class ClientOrderResponse : IResponse
{
    public string ClientName { get; set; }
    public List<Orders> OrderList { get; set; }
    //other properties
}

public class DAL
{
    public IResponse GetAddress(IRequest req)
    {
        //return client address 
    }
    public IResponse GetOrderList(IRequest req)
    {
        //return order list 
    }
}

Variant 1

class Program
{
    static void Main(string[] args)
    {
        IRequest req1 = new ClientAddress();
        req1.ClientId = 1;
        ((ClientAddress)req1).AppId = "abcd";
        DAL d = new DAL();
        IResponse res1 = d.GetAddress(req1);

        IRequest req2 = new ClientOrder();
        req2.ClientId = 1;
        ((ClientOrder)req2).FromDate = "2019/01/01";
        ((ClientOrder)req2).ToDate = "2019/01/15";
        IResponse res2 = d.GetOrderList(req2);
    }
}

Variant 2

class Program
{
    static void Main(string[] args)
    {
        ClientAddress req1 = new ClientAddress();
        req1.ClientId = 1;
        req1.AppId = "abcd";
        DAL d = new DAL();
        IResponse res1 = d.GetAddress(req1);

        ClientOrder req2 = new ClientOrder();
        req2.ClientId = 1;
        req2.FromDate = "2019/01/01";
        req2.ToDate = "2019/01/15";
        IResponse res2 = d.GetOrderList(req2);
    }
}

Please guide me which design is good/bad and why we should use/avoid it or is there any other way to achieve the same.

  • 1
    Well, you should clearly not be casting a local variable to its known type. Downcasting is best avoided generally. – Alex Reinking Jan 16 at 4:13
  • 3
    Please try and edit the question to have a more informative title; just about every question on this site could be under the current title! – Philip Kendall Jan 16 at 5:11
  • 2
    Am I glossing over something or is this question essentially "should I hard cast or not?" – Flater Jan 16 at 10:15
3

Based on just your sample program, there is no benefit to having interfaces since you are trying to access implementation-specific fields such as AppId and FromDate. You should avoid casting and just use the concrete type for this purpose.

Interfaces become useful when you want clients to handle different types of objects in a similar manner through the common interface. For example, you could log the ClientId of all incoming requests regardless of their actual type:

public void LogRequest(IRequest request) {
  Console.WriteLine("Received request from client " + request.ClientId);
}
2

There are problems with the approach you are taking. For example, consider the DAL class:

public class DAL { public IResponse GetAddress(IRequest req) { //return client address } public IResponse GetOrderList(IRequest req) { //return order list } }

GetOrderList states it takes an IRequest. I'm guessing though that if I passed it an instance of ClientAddress, it wouldn't work. As such, it doesn't want an IRequest, it wants a ClientOrder. So you are setting your code up to fail by not specifying that type.

Likewise, that method returns an IResponse, but I'd need to cast it to ClientOrderResponse to actually get at the data returned. So again, it should be returning a ClientOrderResponse.

You appear to be trying to use interfaces in the belief that you should use interfaces, but those interfaces serve no useful purpose in your example code and actually cause harm. So get rid of them and simplify the code down to:

public class ClientAddress
{
    public string ClientId { get; set; }
    public string AppId { get; set; }
}

public class ClientOrder
{
    public string ClientId { get; set; }
    public string FromDate { get; set; }
    public string ToDate { get; set; }
    //other properties
}
public class ClientAddressResponse
{
    public string ClientName { get; set; }
    public string HouseNumber { get; set; }
    public string Area { get; set; }
    public string City { get; set; }
}

public class ClientOrderResponse
{
    public string ClientName { get; set; }
    public List<Orders> OrderList { get; set; }
    //other properties
}

public class DAL
{
    public ClientAddressResponse GetAddress(ClientAddress req)
    {
        //return client address 
    }
    public ClientOrderResponse GetOrderList(ClientOrder req)
    {
        //return order list 
    }
}

class Program
{
    static void Main(string[] args)
    {
        var req1 = new ClientAddress
        {
            ClientId = "1",
            AppId = "abcd"
        };
        DAL d = new DAL();
        var res1 = d.GetAddress(req1);

        var req2 = new ClientOrder
        {
            ClientId = "1",
            FromDate = "2019/01/01",
            ToDate = "2019/01/15"
        };
        var res2 = d.GetOrderList(req2);
    }
}

The only class in your example that would benefit from having an interface is the one you didn't apply an interface to: DAL. Since it will be hard-coded to directly access some data store, then being able to mock it for eg unit tests is essential. So have that implement IDAL and have all of your application, save for Main refer only to IDAL, not DAL directly.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.