Pavel
Pavel

Reputation: 766

C# Generic Method to avoid code duplication

I am working with three different classes that have a common interface. However, the interface, does not include all of the methods and properties for all three. Therefore, I am stuck with a situation where I have code duplication, see below:

if (party is Entity)
{
    var entity = party as Entity;

    txtName1.Text = entity.Name1;

    Address addr = entity.Addresses.FindPrimary();
    txtAddr1.Text = addr.Address1;
    txtCity.Text = addr.City;
    txtZip.Text = addr.Zip;
}
else if (party is CustomerAccount)
{
    var acct = party as CustomerAccount;

    txtName1.Text = acct.Name1;

    Address addr = acct.Addresses.FindPrimary();
    txtAddr1.Text = addr.Address1;
    txtCity.Text = addr.City;
    txtZip.Text = addr.Zip;
}
else if (party is CustomerQuote)
{
    var quote = party as CustomerQuote;

    txtName1.Text = quote.Name1;

    Address addr = quote.Addresses.FindPrimary();
    txtAddr1.Text = addr.Address1;
    txtCity.Text = addr.City;
    txtZip.Text = addr.Zip;
}

Is there a way to create a generic method to handle this situation. Something like the following:

private void getAddressInfo<T>(T party)
{
    var sharedType = party as party.GetType();

    txtName1.Text = sharedType.Name1;

    Address addr = sharedType.Addresses.FindPrimary();
    txtAddr1.Text = addr.Address1;
    txtCity.Text = addr.City;
    txtZip.Text = addr.Zip;
}

Upvotes: 3

Views: 1173

Answers (3)

Nkosi
Nkosi

Reputation: 247018

If you cannot apply all the shared properties to the common interface then you can look into duck typing (Using Type dynamic) where the properties and methods are realized at run time.

You can access the properties and methods of the common interface and then for the other properties and methods you can convert to a dynamic type and call those.

For example, assume a common interface...

public interface ICommonInterface {
    string Name1 { get; }
}

a generic method could look like this...

private void getAddressInfo<T>(T party) where T : ICommonInterface {
    //access common  properties
    txtName1.Text = party.Name1;

    //convert to dynamic to call other properties and methods.
    dynamic sharedType = party;

    Address addr = sharedType.Addresses.FindPrimary();
    if (addr != null) {
        txtAddr1.Text = addr.Address1;
        txtCity.Text = addr.City;
        txtZip.Text = addr.Zip;
    }
}

and used like this

if (party is Entity || party is CustomerAccount || party is CustomerQuote) {
    getAddressInfo(party);
}

While this is a quick workaround, be warned that you wont get compile time errors for the methods and properties that are not defined in the common interface. However, if the code is not valid, errors are caught at run time. But since you are in control of the code then you should make sure that the called properties and methods are there beforehand.

Upvotes: 4

mybirthname
mybirthname

Reputation: 18127

public interface ICompanyAddress
{
    public string Name1 {get; set;}
    public Address Addresses {get; set;}

    //probably other similar stuff
}

public class Entity:ICompanyAddress
{
     //all properties which are needed from the interface
}

//all other classes with same properties should also inherit ICompanyAddress

Your classes should inherit this interface. When you create your objects you will create them this way:

ICompanyAddress entity = new Entity();
ICompanyAddress customerAcc= new CustomerAccount();

You call method like this:

private void SetAddressInfo(ICompanyAddress addressObj)
{

    txtName1.Text = addressObj.Name1;

    Address addr = addressObj.Addresses.FindPrimary();
    txtAddr1.Text = addr.Address1;
    txtCity.Text = addr.City;
    txtZip.Text = addr.Zip;
}

Here how you call the method:

ICompanyAddress customerAcc= new CustomerAccount();

SetAddressInfo(customerAcc);

Upvotes: 4

John Wu
John Wu

Reputation: 52240

Automapper is designed for exactly this purpose. You can set up maps between different object types, and it can automatically map properties of the same name. Here is a simple example. Here it is on NuGet.

If you don't want to use a third party tool, you can perhaps use one of the answers from this question.

The best option, of course, is to modify the domain classes to they all implement an interface for the elements they have in common (e.g. IAddress)... but I'm assuming you asked this question because you don't have the ability to do that in this case.

Upvotes: 4

Related Questions