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