2014-02-21 4 views
2

У меня есть приложение WPF, состоящее из MainWindow, а также множество объектов Page, к которым можно получить доступ через MainWindow. Я в настоящее время User класса будучи инстанцирован в ViewModel в MainWindow, который определяет разрешения свойства, которые связаны с различными свойствами, в соответствующих View:Можно ли создать экземпляр нестатического класса для всего приложения WPF?

public NavigationViewModel() 
{ 
    _currentUser = new User(_currentServerConnection, Environment.UserName); 

Теперь я хотел бы получить доступ к этому же User экземпляра в каждом из Page объект ViewModels. Каков наиболее подходящий способ сделать это с точки зрения дизайна? Я прочитал несколько потоков в StackOverflow и пришел к выводу, что я должен либо сделать этот класс static (что здесь не имеет смысла, этот класс имеет state) или создает экземпляр в каждом ViewModel. Есть ли какие-то другие варианты, которых я мог бы пропустить? О, я тоже читал о классах Singleton, и это явно не рекомендуется. Я чувствую, что мне не хватает фундаментальной концепции здесь.

+1

Синглтона не рекомендуется. Не рекомендуется использовать синглтоны, используемые в неправильном месте или в неправильном порядке. Весь ваш вопрос кричит как «правильный» и «правильный» пример того, когда полезно использовать одноэлемент. – Rhyous

+0

Единственная разница между статикой и синглом заключается в том, что одноэлемент не создается до первого использования. работайте отлично в многопоточных приложениях с блокировкой http://msdn.microsoft.com/en-us/library/ff650316.aspx – Rhyous

+0

Вы также можете смешивать шаблон IOC и Singleton. Вы создаете интерфейс. Вы создаете Singleton, который реализует этот интерфейс. Затем ваш контроллер IOC/фабрика каждый раз использует ваш синглтон. – Rhyous

ответ

2

Синглтон не рекомендуется. Не рекомендуется использовать синглтоны, используемые в неправильном месте или в неправильном порядке.

Весь ваш вопрос кричит как «правильный» и «правильный» пример, когда полезно использовать одноэлемент.

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

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

public class GlobalSettings : IGlobalSettings 
{ 
    public static GlobalSettings Instance 
    { 
     get { return _Instance ?? (_Instance = new GlobalSettings()); } 
    } static GlobalSettings _Instance; 

    public GlobalSettings() 
    { 
    } 

    // More methods/properties here 
} 

Одиночные игры также могут прекрасно работать в многопоточных приложениях с блокировкой. См. Эту статью: http://msdn.microsoft.com/en-us/library/ff650316.aspx

Одиночные игры также очень просты в тестировании или используются в МОК. Любой, кто говорит иначе, просто не понял, что вы можете просто использовать интерфейс для описания синглтона, а затем все ваши объекты, которые используют singleton, могут иметь экземпляр этого интерфейса. Я использую ленивую инъекцию свойств, как показано ниже, если IRA libray уже на месте. Я бы не включил раздувание библиотеки МОК только для этого.

public static IGlobalSettings Settings 
    { 
     get { return _Settings ?? (_Settings = GlobalSettings.Instance); } 
    } static IGlobalSettings _Settings; 

Или вы также можете иметь ваш контроллер IOC/завод просто вернуть ваш экземпляр Singleton каждый раз, когда в качестве интерфейса.

0

Это зависит немного от отношения между User и различными видами моделей.

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

Модель singleton также может хорошо работать здесь, если ваш код одинарный. Однако я вообще не против использования этого шаблона на изменяемых объектах. Сегодня ваше приложение однопоточное, а завтра - нет. Так легко забыть, что вы сделали это критическое предположение неделю или год с этого момента и в конечном итоге поставили себя в очень плохом месте.

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

0

Использование статического класса и статических полей - один из способов его выполнения.

Другой способ - передать объект класса пользователя в качестве параметра конструктору моделей просмотра ваших страниц.

1

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

Если вы хотите немного глубже, у вас может быть класс, который реализует шаблон Singleton, чтобы убедиться, что существует только один экземпляр. У меня есть несколько крупных приложений WPF, которые имеют модели базового представления, которые предоставляют доступ к ряду классов ...Manager, которые предоставляют различные услуги для всех расширяемых моделей представлений.

Один из них - это класс StateManager, который реализует шаблон Singleton и в основном содержит все свойства, которые являются общими для всего приложения.Это свойство базового класса, который предоставляет его:

public StateManager StateManager 
{ 
    get { return StateManager.Instance; } 
} 

И это, как я использую его в интерфейсе:

<RadioButton IsChecked="{Binding StateManager.SomeValue}" Content="all" /> 
1

Другой подход заключается в использовании то, что управляет создание и срок службы объекты, такие как inversion of control container.

Если вы решили изучить этот подход, все, что вам нужно сделать, это:

  1. Иметь единую точку входа в приложение (состав корня), где вы говорите контейнеровозы, какие объекты и каким образом будут доступны (в WPF, это будет App)
  2. Дизайна классов так, чтобы они могли использовать инъекции зависимостей (то есть ваши модели вида не создаст экземпляр пользователя, но вместо того, чтобы ожидать , что будет обеспечиваться через Конструктор инъекции)
  3. Стоп беспокоиться об объектах жизни от просмотра кода модели (она не должна быть в пределах вида модели обязанностей-сфера)

Пример с Autofac:

// App.xaml.cs 
var builder = new ContainerBuilder(); 
builder.RegisterType<User>() 
    .WithParameter("userName", Environment.UserName) 
    // tell container only one instance of this object should be ever created 
    .SingleInstance(); 


// ViewModel.cs 
public ViewModel(User user) 
{ 
    // we don't care at this point whether user is single instance or not; 
    // it's container's responsibility to handle it for us 
    this.user = user; 
} 

Инъекционное соединение текущего сервера для пользователя может быть проблематичным (поскольку он не будет доступен при настройке корневого состава), но для устранения этой проблемы достаточно использовать factory method pattern.

Смежные вопросы