Избегание глобальных данных в бизнес-логике, которые совместно используются настольными и веб-приложениями - PullRequest
0 голосов
/ 07 января 2011

Я создаю магазин ECommerce, который настраивается администраторами через приложение c # desktop (Windows Forms) и используется конечными пользователями через веб-сайт.В рамках моего дизайна довольно много бизнес-логики распределяется между настольным компьютером и веб-компонентами.Использование настольного или веб-приложения требует аутентификации.

По мере того, как я его создаю, я улавливаю некоторые запахи кода, потому что я все время вынужден добавлять параметр в конструкторы классов, которые идентифицируют информациюкакой тип пользователя использует бизнес-логику (т. е. IP-адрес пользователя, перечисление для настольного компьютера или сети, идентификационный номер пользователя системы и т. д.).

Этот класс идентификаторов, в котором хранится эта информация, напоминает глобальные данные, которых я стараюсь избегать из-за принципов SOLID и т. Д., Но мне действительно трудно найти лучшее решение для того, как классможет иметь быстрый доступ ко всей необходимой информации.

Есть ли готовое решение этой проблемы?

Ответы [ 4 ]

0 голосов
/ 08 января 2011

Еще один метод - заставить посредника хранить некоторые данные, затем поместить их туда и извлечь.

Вам все равно придется передать какой-то уникальный идентификатор.

Тем не менее, я быстро проверил, что платформа EnterpriseLibrary.Caching ... если вы сконфигурируете backendstore как db (а не только в памяти), то и веб-форма, и приложение winform могут получить данные.Вот пример, чтобы вы начали:

  <add expirationPollFrequencyInSeconds="240" maximumElementsInCacheBeforeScavenging="1000"
    numberToRemoveWhenScavenging="10" backingStoreName="CacheViaADatabase"
    type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="IPrincipalCache" />

</cacheManagers>
<backingStores>

  <add databaseInstanceName="CachingConnectionString" partitionName="CS" encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.Database.DataBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
       name="CacheViaADatabase"/>


</backingStores>

0 голосов
/ 07 января 2011

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

Какой бы подход вы ни использовали, глобальный или переданный, для таких ключевых классов, как этот, моя рекомендация, вероятно, будет заключаться в том, чтобы каким-то образом абстрагировать его, чтобы впоследствии вы могли легче изменить реализацию (и упростить тестирование) , Вы можете сделать это, извлекая интерфейс из этого класса, и таким образом каждый из ваших различных других классов должен быть привязан только к интерфейсу, а не к реализации. Если вы хотите, вы также можете абстрагировать его на один уровень дальше и просто передать некоторый класс Factory, который возвращал реализацию базового интерфейса при необходимости.

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

0 голосов
/ 07 января 2011

Я думаю, вы хотите создать свой собственный объект IPrincipal.

Этот объект является общим как для winform, так и для веб-приложения.

Хотя вы можете назначить IIDentity свойству IPrincipal.IIDentity ........ Вы должны быть более заинтересованы в IPrincipal (вашей пользовательской конкретной версии), а не в IIdentity.

Ваш пользовательский IPrincipal будет иметь метод .IsInRole. Хотя мне не нравится безопасность на основе ролей (ПРАВА или РАЗРЕШЕНИЯ лучше, я считаю), существуют обходные пути. Смотрите мое обсуждение здесь: http://sholliday.spaces.live.com/blog/cns!A68482B9628A842A!846.entry и вот одна работа вокруг .IsInRole вещи http://www.lhotka.net/weblog/CommentView,guid,9efcafc7-68a2-4f8f-bc64-66174453adfd.aspx

Я бы создал один IPrincipal (ваша собственная версия) (например, MySuperCoolPrincipal.cs), абстрактный IIDentity (ваша собственная абстрактная версия, такая как MyAbractIIdenity: IIDentity) (

Затем вы можете ссылаться на MyAbractIIdenity в большей части вашего кода. Вы можете конвертировать в некоторых случаях, если это необходимо. (Например, если вам нужен IP-адрес вашего MyWebUser).

Помните, что если вы хотите проверить, МОЖЕТ ЛИ ЧТО-ТО ДЕЛАТЬ, то вы проверяете IIPrincipal, а НЕ ИХ ИДЕНТИЧНОСТЬ.

Могу ли я редактировать сотрудника? Проверьте IPrincipal. Могу ли я увидеть этот отчет? Проверьте IPrincipal. Могу ли я просмотреть специальное / секретное свойство этого объекта? Проверьте IPrincipal.

В большинстве случаев вас не волнует кто. Вы заботитесь о том, что они могут сделать.

.......

Теперь предположим, что пользователь имеет право / разрешение на "EDIT_EMPLOYEE". Пользователь имеет это право, но пользователь не может редактировать ~~ каждого сотрудника в системе. Они могут редактировать некоторых сотрудников.

Так что вы можете иметь два права. EDIT_EMPLOYEE_ANY_DEPT EDIT_EMPLOYEE_HOME_DEPT_ONLY

Видите разницу? И когда вы пытаетесь вызвать сотрудников, которых пользователь может редактировать, вам, возможно, придется проверить имеющуюся у вас пользовательскую IIDentity.
Возможно, вы создали свойство под названием MyAbractIIdenity.HomeDepartmentKey

Вы можете проверить это свойство, чтобы определить, каких сотрудников вы можете редактировать, на основании разрешения: EDIT_EMPLOYEE_HOME_DEPT_ONLY

Если я что-то упустил, дайте мне знать.

Но я думаю, что вы можете передать только MySuperCoolPrincipal.

Посмотрите мою статью выше. Разработанный мной анти-паттерн помогает понять, что я говорю о правах (разрешениях) против ролей. И я думаю, что это поможет с вещами IIdentity vs IPrincipal, о которых я упоминал выше.

0 голосов
/ 07 января 2011

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

...