Метод расширения и явное приведение - PullRequest
8 голосов
/ 29 ноября 2011

Я использую класс из какой-то сборки (исходный код недоступен), поэтому невозможно изменить их код Мне нужно добавить метод расширения для явного оператора приведения, есть ли способ добиться этого? (Я пытался добавить как обычный метод расширения, но безуспешно)

 public static explicit operator MembershipUser(this MembershipUser membership, User user)
    {
        return new MembershipUser("SimplyMembershipProvider", user.UserName, user.UserId, user.Email, null, null, user.IsApproved, user.IsLocked,
            user.CreateDate, user.LastLoginDate, user.LastActivityDate, user.CreateDate, DateTime.MinValue);
    }

как я могу решить это?

Ответы [ 4 ]

12 голосов
/ 29 ноября 2011

Вы не можете перегружать операторы с помощью методов расширения.

Лучшее, что вы можете сделать с помощью метода расширения:

public static MembershipUser ConvertToMembershipUser(this User user)
{
    return new MembershipUser("SimplyMembershipProvider", 
                              user.UserName, 
                              user.UserId, 
                              user.Email, 
                              null, 
                              null, 
                              user.IsApproved, 
                              user.IsLocked,
                              user.CreateDate, 
                              user.LastLoginDate, 
                              user.LastActivityDate,
                              user.CreateDate, 
                              DateTime.MinValue);
}

MembershipUser membershipUser = aUser.ConvertToMembershipUser();
6 голосов
/ 29 ноября 2011

Как уже говорили другие, вы не можете перегружать операторы, используя методы расширения - но простой метод расширения все равно будет полезен:

public static MembershipUser ToMembershipUser(this User user)
{
    return new MembershipUser("SimplyMembershipProvider",
        user.UserName, user.UserId, user.Email, null, null, 
        user.IsApproved, user.IsLocked, user.CreateDate, 
        user.LastLoginDate, user.LastActivityDate, user.CreateDate,
        DateTime.MinValue);
}

Тогда просто используйте его как:

User user = ...;
MembershipUser membershipUser = user.ToMembershipUser();

Лично я нахожу это более ясным, чем использование явного преобразования в любом случае - я очень редко занимаюсь перегрузкой операторов.В частности, учитывая, что классы безусловно sound связаны, наивный пользователь может ожидать, что этот код:

User user = ...;
MembershipUser membershipUser = (MembershipUser) user;

... будет нормальным эталонным преобразованием, ожидая, что MembershipUser будеткласс, производный от User.Это важно с точки зрения идентификации объекта - если бы это было , то это не изменило бы вовлеченный объект (и изменения в объекте, на который ссылается user, все равно были бы видны через membershipUser).

Создание метода ToMembershipUser упрощает преобразование одной формы в новый объект другого типа.Все ИМО, конечно :) 1021 *

2 голосов
/ 29 ноября 2011

Нет, вы не можете добавить расширение преобразования.

Явные или неявные преобразования могут быть определены только в том случае, если вы управляете исходным кодом для одного из задействованных типов. В вашем случае вы можете контролировать либо MembershipUser, либо User, вам не нужно контролировать оба. Но вы должны контролировать один.

Если вы не управляете ни тем, ни другим, вам просто нужно определить преобразование в методе другого класса, задачей которого является управление таким преобразованием.

class UserConverter 
{
    public MembershipUser ConvertFrom(User user) 
    {
        return ...
    }
}
0 голосов
/ 29 ноября 2011

Не говорите, что это хорошая практика (прочитайте другие ответы, почему вы не хотите этого, но если классы не запечатаны, это возможно, просто не используя методы расширения).

По сути, вы можете создать суррогатный класс, наследующий пользователя, который определяет оператор приведения, что-то вроде:

    class UserSurrogate : User
    {
        public static explicit operator UserSurrogate(MemberShipUser other)
        {
            return  new UserSurrogate() { Name = other.Name };
        }
    }

    class User
    {
        public string Name { get; set; }
    }

    class MemberShipUser
    {
        public string Name { get; set; }   
    }
...