Как мне сохранить объект в веб-сервисе asp.net, чтобы бизнес-объекты могли ссылаться на этот объект? - PullRequest
1 голос
/ 09 августа 2010

Я создаю веб-сервис ASP.NET, который будет использоваться внутри моей компании. Регистрация исключений и трассировки / аудита будет выполняться классом веб-службы, а также бизнес-объектами, которые будет вызывать веб-служба. Ведение журнала обрабатывается экземпляром класса внутренней поддержки журнала. Помощник журнала должен быть экземпляром, так как он отслеживает состояние, и справочным гидом, который используется для связи сообщений журнала в группы.

Раньше мы обрабатывали эту ситуацию, передавая ссылки на экземпляр помощника журнала из класса в класс, используя параметры метода. Я пытаюсь найти надежный способ найти способ хранения и доступа к экземпляру в течение всего вызова без необходимости явной его передачи.

Я пытаюсь сохранить экземпляр в HTTPContext на ранних этапах вызова веб-службы. Когда это понадобится моим бизнес-объектам позднее во время вызова, они получат к нему доступ как к свойству базового класса, от которого наследуются все мои объекты.

Сначала я попытался сохранить экземпляр в Context.Cache веб-службы. Похоже, это сработало, и мои исследования привели меня к мысли, что кэш будет безопасным для потоков. Только после того, как я начал вызывать веб-сервис из более чем 3 одновременных сессий, экземпляр регистратора будет совместно использоваться от вызова к вызову, а не будет заново создаваться новым для каждого вызова. Я попробовал Context.Application и нашел очень похожие результаты с хранилищем Cache.

Мне удалось найти то, что выглядит как полезное решение с Context.Session. Это требует, чтобы я использовал EnableSession = true в атрибутах каждого метода, но он, кажется, сохраняет экземпляр уникальным для каждого вызова. У меня нет необходимости отслеживать данные между вызовами, поэтому я не храню сеансовые куки в клиентском пространстве.

Является ли сессия оптимальной точкой хранения для моих нужд? Это кажется немного тяжелым, учитывая, что мне не нужно отслеживать сеанс между вызовами. Я открыт для предложений или критики. Я уверен, что кто-то посоветует использовать встроенную систему трассировки или системы вроде Elmah. Это может быть вариантом на будущее, но сейчас у меня нет времени, необходимого, чтобы пойти по этому пути.

Обновление: я должен уточнить, что эта служба должна будет работать на .Net Framework 2.0. Мы находимся в процессе перехода на 3.5 / 4.0, но наш текущий рабочий сервер - Win2000 с максимальным значением 2.0.

Ответы [ 3 ]

2 голосов
/ 09 августа 2010

Вы можете попробовать использовать OperationContext.Current. Это позволит вам хранить переменные в течение всего времени обращения к веб-службе.

Отредактировано для объявления возможного Нет решения WCF: Поскольку у вас нет WCF, вы можете создать что-то вроде локального хранилища потоков, создав статическую карту идентификаторов потоков для вашего объекта. Просто убедитесь, что вы правильно очищаете эту статическую карту после завершения запросов, иначе следующий вызов, использующий этот поток, подберет ваш объект. Кроме того, убедитесь, что заблокировали карту при доступе к ней.

1 голос
/ 09 августа 2010

Насколько я понимаю, в прошлом вы использовали эти бизнес-объекты в приложении Windows Forms?

Ваши бизнес-объекты не должны зависеть от какого-либо окружающего объекта. Вместо этого вы должны использовать внедрение конструктора или внедрение свойства для передачи объекта регистратора бизнес-объектам. Регистратор должен быть представлен интерфейсом, а не конкретным классом. Бизнес-объектам должна быть передана ссылка на некоторый класс, который реализует этот интерфейс. Они должны никогда не знать, где хранится этот объект. Это позволит вам тестировать бизнес-объекты вне веб-службы.

Затем вы можете хранить объект регистрации где угодно. Я бы предложил сохранить его в HttpContext.Current.Items, который действителен только для текущего запроса.


public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message) {}
}

public class BusinessObjectBase
{
    public BusinessObjectbase(ILogger logger)
    {
        Logger = logger;
    }

    protected ILogger Logger {get;set;}
}

public class BusinessObject : BusinessObjectBase
{
    public void DoSomething()
    {
        Logger.Log("Doing something");
    }
}
0 голосов
/ 10 августа 2010

Насколько я понимаю, класс ASMX создается для каждого вызова. Следовательно, создается впечатление, что вы можете создать экземпляр класса log-helper в конструкторе ASMX и сохранить его в переменной экземпляра. Вся обработка в классе ASMX будет ссылаться на эту переменную экземпляра. Таким образом, один и тот же экземпляр помощника по журналу будет использоваться на протяжении всего жизненного цикла одного вызова веб-службы и НЕ будет совместно использоваться несколькими вызовами.

Скорее всего, это будет реализовано в общем суперклассе, от которого наследуются все ваши классы ASMX. Хотя я полагаю, что ничто не мешает вам реализовывать это снова и снова в каждом классе ASMX, если по какой-то причине вы отказываетесь от общего суперкласса.

...