views:

160

answers:

4

Hi guys,

I'm beginning to fall in love with Extension Methods, but I just don't know how to create an EM only for a determinate Object type.

I have for example:

public static void AddPhoneNumberToContact(this Contact contact, PhoneType type, String number)
{
    lock (contact)
    {
        PhoneRow pr = PhoneRow.CreateNew();
        pr.SetDefaults();
        pr.PtypeIdx = type;
        pr.PhoneNumber = number;
        contact.Phones.Add(pr);
        pr = null;
    }
}

My problem is that I want to also Have this method in the Person object, and that is why I named

AddPhoneNumberToContact
AddPhoneNumberToPerson

Is there a way to have AddPhoneNumber and deal with the object that is provided?

or the solution is to have

public static void AddPhoneNumber(this object contact, ...
{
   ...

   if(typeof(Contact) == contact)
      ((Contact)contact).Phones.Add(pr);
   else if(typeof(Person) == contact)
      ((Person)contact).Phones.Add(pr);
}

Thank you.

+5  A: 

Make Contact and Person implement common interface - say IContactWithPhoneNumbers - and then write an extension method "for this interface".

public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}
Anton Gogolev
Contact and Person are protected, it's from a SDK.
balexandre
+8  A: 

How about writing two extension methods:

public static void AddPhoneNumber(this Contact contact, PhoneType type);

and

public static void AddPhoneNumber(this Person person, PhoneType type);

Looks cleaner to me.

If there's some common code between the two, extract that into a separate method.

Frederick
How dumb can I be sometimes!!! :) Thanks
balexandre
forgot all about multiple Functions with the same name :'( (and I use it a lot! but it was a new thing to me, ExMethods (!))
balexandre
+1  A: 

Reading your comments (objects are from an SDK and are not editable). I would probably do something like this:

public class Util
{
    //common util method
    public static void AddPhoneNumber(object obj, string phoneNumber)
    {
         if(obj is Contact)
             ((Contact)contact).Phones.Add(phoneNumber);
         else if(obj is Person)
             ((Person)contact).Phones.Add(phoneNumber);
    }

    //extension method for Person
    public static void AddPhoneNumber(this Person p, string phoneNumber)
    {
        AddPhoneNumber((object)p, phoneNumber);
    }

    //extension method for Contact
    public static void AddPhoneNumber(this Contact c, string phoneNumber)
    {
        AddPhoneNumber((object)c, phoneNumber);
    }
}

I do think the best practice though when you have control of the underlying objects would be to implement a common interface.

spoon16
A: 

You might make your extension method generic, e.g.:

public static void AddPhoneNumberToContact<T>(
    this T contact,
    PhoneType type,
    String number
)
{
    PhoneRow pr = PhoneRow.CreateNew();
    pr.SetDefaults();
    pr.PtypeIdx = type;
    pr.PhoneNumber = number;
    ((T)contact).Phones.Add(pr);
    pr = null;
}

You won't be able to use lock because "'T' is not a reference type as required by the lock statement", so you might have to return some value.

If it complains about not being able to resolve the Phones method on type T, you could:

Pass in some function delegate that would take type T, return nothing, and perform the action ((T)contact).Phones.Add(pr);.

Or you could create an interface like the following:

public interface IPhoneable
{
    IList<Phone> Phones();
}

Then, once you have that interface, you can add the following to your generic extension method:

public static void AddPhoneNumberToContact<T>(
    this T contact,
    PhoneType type,
    String number
) where T : IPhoneable {...}

Here, T is still a generic type, but now your AddPhoneNumberToContact method has the requirement that, whatever T is, it inherits from the IPhoneable interface, which you just defined to have the Phones() method.

See also C# Extension Method for Generic Collections.

Sarah Vessels
I will look upon this better, thank you for the insight.
balexandre