Reputation: 766
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
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
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
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