ProfileCommon - литье во время выполнения не выполняется

Резюме: Null возвращается после того, как базовый класс добавлен к производному классу. Тем не менее, объект базового класса кажется ОК до кастинга.

Детали: Я переписываю старое приложение asp.net WebForms, чтобы иметь возможность расширять его с помощью подхода MVC. В рамках процессов я конвертирую проект веб-сайта в проект веб-приложения. В этом случае класс ProfileCommon не генерируется автоматически. Итак, я скопировал определение автогенерированного класса из более старого проекта и поместил его как utils\ProfileCommon.cs. Содержимое файла (упрощено до одного свойства, которое также было переименовано из чешского эквивалента):

using System;
using System.Web;
using System.Web.Profile;

namespace proj_app.utils
{
    public class ProfileCommon : System.Web.Profile.ProfileBase
    {
        public virtual string Name {
            get { return ((string)(this.GetPropertyValue("Name"))); }
            set { this.SetPropertyValue("Name", value); }
        }

        public static ProfileCommon GetProfile(string username)
        {
            return ((ProfileCommon)(ProfileBase.Create(username)));
        }
    }
}

Разница также в том, что я удалил virtual из метода GetProfile() и сделал его static. (ProfileBase не имеет метода GetProfile(), поэтому должно быть хорошо, правильно?)

Код компилируется отлично. Тем не менее, я могу наблюдать в браузере (свободно переведенный, номера строк не совпадают с примером):

The object of the ProfileCommon type cannot be casted to proj_app.utils.ProfileCommon.
Description: ... unhandled exception during the web request...

Details about the exception: The object of the ProfileCommon type cannot be casted to proj_app.utils.ProfileCommon.

Zdrojová chyba:

Line 36:         public static ProfileCommon GetProfile(string username)
Line 37:         {
Line 38:             return ((ProfileCommon)(ProfileBase.Create(username)));
Line 39:         }
Line 40:     }


Source file: d:\__RizeniProjektu\aplikace\proj_app\utils\ProfileCommon.cs    Line: 38

Stack trace:
[InvalidCastException: Objekt typu ProfileCommon nelze přetypovat na typ proj_app.utils.ProfileCommon.]
   proj_app.utils.ProfileCommon.GetProfile(String username) in d:\__RizeniProjektu\aplikace\proj_app\utils\ProfileCommon.cs:38
   Users_seznam.Page_Load(Object sender, EventArgs e) in d:\__RizeniProjektu\aplikace\proj_app\Users\seznam.aspx.cs:29
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
   System.Web.UI.Control.OnLoad(EventArgs e) +92
   System.Web.UI.Control.LoadRecursive() +54
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

При отладке ProfileBase.Create(username) возвращает объект, где правильное значение для свойства Name имеет ожидаемое значение (отладчик знает, как получить значение). Тем не менее, после трансляции результирующая ссылка объекта null. (Я должен признать, что я не очень хорош в С#, я пришел из С++.) Я также попытался разделить эту команду, чтобы получить ProfileBase p = ProfileBase.Create(username); (объект не является нулевым), и только затем передать его в ProfileCommon q = p as ProfileCommon; (значение q равно нулю).

Обновление: Странно. Я переименовал свой класс в ProfileComm, очистил проект, скомпилированный с нуля. В каталоге нет строки ProfileCommon (а не в источниках, а не в двоичных файлах, *.suo, *.dll, *.pdb, а не в любом другом файле). Даже имя файла было переименовано в ProfileComm.cs, чтобы не иметь ProfileCommon в *.csproj. Источник GetProfile() был изменен на:

public class ProfileComm : System.Web.Profile.ProfileBase
{
    ...
    public static ProfileComm GetProfile(string username)
    {
        object p = ProfileBase.Create(username);
        Type t = p.GetType();
        string s = t.Name;

        return ((ProfileComm)(p));
    }
}

Теперь информация об исключении в браузере читается (переводится с другого языка): System.InvalidCastException: Object of the type ProfileCommon cannot be casted to the type proj_app.utils.ProfileComm.

При отладке отладчик показывает, что тип p равен ProfileCommon:

What the debugger shows about the type

Я понятия не имею, откуда произошло имя типа ProfileCommon. Может ли быть связано с версией .NET framework? Что я должен проверить? Может ли класс ProfileCommon по-прежнему генерировать динамически каким-то образом?

Ответ 1

ASP.NET автоматически создает класс ProfileCommon, который наследует от ProfileBase при запуске приложения. Если вы хотите использовать свою собственную реализацию профиля, вам нужно явно указать ее в web.config. Что-то вроде:

<profile inherits="proj_app.utils.ProfileCommon">
....

Таким образом, ProfileBase.Create вернет экземпляр вашего указанного типа вместо автоматически сгенерированного.

MSDN для более подробной информации

Ответ 2

Кажется, у вас есть два типа ProfileCommon, вы должны проверить свой источник, чтобы подтвердить это. Вы также можете быть более конкретным и ProfileBase.Create(username) вернуть proj_app.utils.ProfileCommon вместо ProfileCommon.

Также для отладки, возможно, попробуйте и посмотрите, что компилятор считает, что объект действительно есть, см. это сообщение: Не удалось разрешить тип: Проблема, пока я нахожу специальный класс в С#


Кажется, вы противоречите классу ASP.NET, я бы либо создал новый класс целиком, либо создал суперкласс класса ASP.NET ProfileCommon.

ASP.NET использует класс ProfileBase для создания класса, используемого для профиля пользователя. Когда запущено приложение с включенным профилем пользователя, ASP.NET создает новый класс типа ProfileCommon, который наследуется от класса ProfileBase. Сильно типизированные аксессоры добавляются в класс ProfileCommon для каждого свойства, определенного в разделе конфигурации профиля. Сильно типизированные аксессоры класса ProfileCommon вызывают методы GetPropertyValue и SetPropertyValue базового класса ProfileBase для извлечения и установки значений свойств профиля соответственно. Экземпляр класса ProfileCommon устанавливается как значение свойства Profile для приложения ASP.NET.

https://msdn.microsoft.com/en-us/library/system.web.profile.profilebase(v=vs.110).aspx