9

我开始爱上扩展方法,但我只是不知道如何仅为确定的 Object 类型创建 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);
}

谢谢你。

4

5 回答 5

13

写两个扩展方法怎么样:

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

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

对我来说看起来更干净。

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

于 2009-02-05T10:31:20.537 回答
7

制作ContactPerson实现通用接口 - 比如说IContactWithPhoneNumbers- 然后为“这个接口”编写一个扩展方法。

public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}
于 2009-02-05T10:27:31.637 回答
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);
    }
}

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

于 2009-02-05T10:37:32.600 回答
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' 不是 lock 语句所需的引用类型”,因此您可能必须返回一些值。

如果它抱怨无法解析 T 类型的 Phones 方法,您可以:

传入一些函数委托,该委托将采用 T 类型,不返回任何内容,然后执行操作((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它继承自您刚刚定义为具有 Phones() 方法的 IPhoneable 接口。

另请参阅通用集合的 C# 扩展方法

于 2009-07-02T16:44:13.823 回答
0

如果您无法更改 Person 和 Contact ,您可以创建它们的子类并让它们实现公共接口。

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

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var p = new MyPerson();
        p.Name = "test";
        p.AddPhonenumber("555-2356");
        Console.WriteLine(string.Join(", ", p.Phonenumber));

        var c = new MyContact();
        c.Name = "contact";
        c.AddPhonenumber("222-235");
        Console.WriteLine(string.Join(", ", c.Phonenumber));
    }
}


public class Contact
{
    public Contact() {
        this.Phonenumber = new List<string>();
    }
    public string Name { get; set; }
    public List<string> Phonenumber { get; set; }
    public string Foo { get; set; }
}
public class Person
{
    public Person() {
        this.Phonenumber = new List<string>();
    }
    public string Name { get; set; }
    public List<string> Phonenumber { get; set; }
    public string Bar { get; set; }
}

public class MyContact: Contact, IType {
}

public class MyPerson: Person, IType {
}


public static class Extensions {
    public static void AddPhonenumber(this IType type, string number){
        type.Phonenumber.Add(number);
    }
}

public interface IType {
    string Name {get; set; }
    List<string> Phonenumber {get; set;}
}
于 2017-06-08T09:49:41.010 回答