重构:通用扩展方法

时间:2013-10-30 00:09:01

标签: c# generics extension-methods

我有一个扩展方法,检查对象的类型,然后填充其成员属性

public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) 
where T: MyEntity
            {
                var agenda = entity as Agenda;

                if (agenda != null)
                {
                    agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
                }

                var participant = entity as Participant;

                if (participant != null)
                {
                    participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
                }

            }

我可以进一步将其重构为类似的内容以使其更通用吗?

 public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T : MyEntity
        {
            var obj = entity as Agenda || entity as Participant;

            if (obj != null)
            {
                obj.Meeting = meetingRepository.GetMeetingById(obj.MeetingId);
            }
        }
    }

PS:我不想把对象的属性Meeting放在Base类中(MyEntity)

2 个答案:

答案 0 :(得分:6)

我个人只会使用重载:

public static void LoadMeeting(this Agenda agenda, IMeetingRepository meetingRepository) 
{
    if (agenda != null)
    {
         agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
    }
}
public static void LoadMeeting(this Participant participant, IMeetingRepository meetingRepository) 
{
    if (participant != null)
    {
        participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
    }
}

除非您有一些提供Meeting属性的共享契约(基类或接口实现),否则您无法使用单个泛型方法执行此操作。

替代方案是创建一个共享接口,即:IMeeting,然后约束到:

public interface IMeeting
{
   public Meeting Meeting { get; set; }
   public int MeetingId { get; }
}

然后你可以写:

public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) 

其中T:IMeeting             {                 if(entity!= null)                 {                     entity.Meeting = meetingRepository.GetMeetingById(entity.MeetingId);                 }             }

当您使用EF时,您可以在部分类中实现此接口:

public partial class Agenda : MyEntity, IMeeting
{
}

答案 1 :(得分:1)

您可能希望尽早返回该方法,因为您必须处理类及其基类。

public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity
        {
            var agenda = entity as Agenda;

            if (agenda != null)
            {
                agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
                return;
            }

            var participant = entity as Participant;

            if (participant != null)
            {
                participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
                return;
            }
        }

您可能还会考虑表格方法:

    public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity {
        var name = entity.GetType().Name;
        if (Table.ContainsKey(name)) {
            Table[name](entity, meetingRepository);
            }
        }

表格是:

static Dictionary<String, Action<MyEntity, IMeetingRepository>> Table = new Dictionary<String, Action<MyEntity, IMeetingRepository>>();

它被初始化为:

        Table.Add("Agenda", (agenda, meetingRepository) => { 
            ((Agenda)agenda).Meeting = meetingRepository.GetMeetingById(((Agenda)agenda).MeetingId); }); 
        Table.Add("Participant", (participant, meetingRepository) => { 
            ((Participant)participant).Meeting = meetingRepository.GetMeetingById(((Participant)participant).MeetingId); }); 

显然,您的表必须是静态的,并且可用于您的扩展方法(例如在包含类中)。