如何将常用扩展方法应用于第三方SDK中的多个不相关类型?

时间:2009-02-05 10:23:41

标签: c# extension-methods

我开始爱上扩展方法,但我只是不知道如何为确定的对象类型创建EM。

我有例如:

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;
    }
}

我的问题是我想在Person对象中也有这个方法,这就是我命名

的原因
AddPhoneNumberToContact
AddPhoneNumberToPerson

有没有办法让AddPhoneNumber处理提供的对象?

或解决方案是

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);
}

谢谢。

5 个答案:

答案 0 :(得分:11)

如何编写两种扩展方法:

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

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

对我来说看起来更干净。

如果两者之间存在一些共同的代码,请将其提取到单独的方法中。

答案 1 :(得分:7)

ContactPerson实现通用接口 - 比如IContactWithPhoneNumbers - 然后为此接口编写扩展方法。

public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}

答案 2 :(得分:2)

阅读您的评论(对象来自SDK并且不可编辑)。我可能会做这样的事情:

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);
    }
}

我确实认为,当您控制底层对象时,最好的做法是实现一个通用接口。

答案 3 :(得分:0)

您可以将扩展方法设为通用,例如:

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;
}

您将无法使用lock,因为“'T'不是锁定语句所要求的引用类型”,因此您可能必须返回一些值。

如果它抱怨无法解决类型T上的电话方法,您可以:

传递一些{T}类型的function delegate,不返回任何内容,然后执行((T)contact).Phones.Add(pr);行动。

或者您可以创建如下界面:

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

然后,一旦拥有该界面,就可以将以下内容添加到通用扩展方法中:

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

在这里,T仍然是一个泛型类型,但现在你的AddPhoneNumberToContact方法要求,无论T是什么,它都从IPhoneable接口继承,你刚才定义了它的电话(方法。

另见C# Extension Method for Generic Collections

答案 4 :(得分:0)

如果你不能改变Person和Contact,你可以创建它们的子类,让它们实现公共接口。

在扩展方法中,将公共接口声明为参数:

{{1}}