2010-12-22 2 views
7

피드백이 좋을 지 모르지만 이것은 질문보다 많은 논평입니다. 우리가하고있는 새로운 프로젝트를위한 사용자 인터페이스를 만드는 임무가 주어졌습니다. 우리는 WPF를 사용하기를 원하며 모든 현대적인 UI 디자인 기술을 배우고 싶었습니다. 저는 WPF에 대해 처음으로 익숙해 졌기 때문에 사용할 수있는 것을 조사하고 있습니다. MVVM Light Toolkit을 사용할 때 (주로 "Blendability"및 EventToCommand 동작 때문에!) 정착했다고 생각하지만 IoC도 통합하려고했습니다. 그래서, 여기 제가 생각해내는 것이 있습니다. MVC Light 프로젝트에서 기본 ViewModelLocator 클래스를 수정하여 UnityContainer를 사용하여 종속성 주입을 처리했습니다. 3 개월 전에이 용어의 90 %가 무엇을 의미하는지 모르겠다 고 생각하면, 나는 올바른 방향으로 가고 있다고 생각합니다. MVVM Light Toolkit과 Unity 2.0 결합

// Example of MVVM Light Toolkit ViewModelLocator class that implements Microsoft 
// Unity 2.0 Inversion of Control container to resolve ViewModel dependencies. 

using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    public class ViewModelLocator 
    { 
     public static UnityContainer Container { get; set; } 

     #region Constructors 
     static ViewModelLocator() 
     { 
      if (Container == null) 
      { 
       Container = new UnityContainer(); 

       // register all dependencies required by view models 
       Container 
        .RegisterType<IDialogService, ModalDialogService>(new ContainerControlledLifetimeManager()) 
        .RegisterType<ILoggerService, LogFileService>(new ContainerControlledLifetimeManager()) 
        ; 
      } 
     } 

     /// <summary> 
     /// Initializes a new instance of the ViewModelLocator class. 
     /// </summary> 
     public ViewModelLocator() 
     { 
      ////if (ViewModelBase.IsInDesignModeStatic) 
      ////{ 
      //// // Create design time view models 
      ////} 
      ////else 
      ////{ 
      //// // Create run time view models 
      ////} 

      CreateMain(); 
     } 

     #endregion 

     #region MainViewModel 

     private static MainViewModel _main; 

     /// <summary> 
     /// Gets the Main property. 
     /// </summary> 
     public static MainViewModel MainStatic 
     { 
      get 
      { 
       if (_main == null) 
       { 
        CreateMain(); 
       } 
       return _main; 
      } 
     } 

     /// <summary> 
     /// Gets the Main property. 
     /// </summary> 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
      "CA1822:MarkMembersAsStatic", 
      Justification = "This non-static member is needed for data binding purposes.")] 
     public MainViewModel Main 
     { 
      get 
      { 
       return MainStatic; 
      } 
     } 

     /// <summary> 
     /// Provides a deterministic way to delete the Main property. 
     /// </summary> 
     public static void ClearMain() 
     { 
      _main.Cleanup(); 
      _main = null; 
     } 

     /// <summary> 
     /// Provides a deterministic way to create the Main property. 
     /// </summary> 
     public static void CreateMain() 
     { 
      if (_main == null) 
      { 
       // allow Unity to resolve the view model and hold onto reference 
       _main = Container.Resolve<MainViewModel>(); 
      } 
     } 

     #endregion 

     #region OrderViewModel 

     // property to hold the order number (injected into OrderViewModel() constructor when resolved) 
    public static string OrderToView { get; set; } 

     /// <summary> 
     /// Gets the OrderViewModel property. 
     /// </summary> 
     public static OrderViewModel OrderViewModelStatic 
     { 
      get 
      { 
       // allow Unity to resolve the view model 
       // do not keep local reference to the instance resolved because we need a new instance 
       // each time - the corresponding View is a UserControl that can be used multiple times 
       // within a single window/view 
       // pass current value of OrderToView parameter to constructor! 
       return Container.Resolve<OrderViewModel>(new ParameterOverride("orderNumber", OrderToView)); 
      } 
     } 

     /// <summary> 
     /// Gets the OrderViewModel property. 
     /// </summary> 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
      "CA1822:MarkMembersAsStatic", 
      Justification = "This non-static member is needed for data binding purposes.")] 
     public OrderViewModel Order 
     { 
      get 
      { 
       return OrderViewModelStatic; 
      } 
     } 
     #endregion 

     /// <summary> 
     /// Cleans up all the resources. 
     /// </summary> 
     public static void Cleanup() 
     { 
      ClearMain(); 
      Container = null; 
     } 
    } 
} 

그리고 MainViewModel 클래스 도시 의존성 주입 용도 :

using GalaSoft.MvvmLight; 
using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     private IDialogService _dialogs; 
     private ILoggerService _logger; 

     /// <summary> 
     /// Initializes a new instance of the MainViewModel class. This default constructor calls the 
     /// non-default constructor resolving the interfaces used by this view model. 
     /// </summary> 
     public MainViewModel() 
      : this(ViewModelLocator.Container.Resolve<IDialogService>(), ViewModelLocator.Container.Resolve<ILoggerService>()) 
     { 
      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
      } 
      else 
      { 
       // Code runs "for real" 
      } 
     } 

     /// <summary> 
     /// Initializes a new instance of the MainViewModel class. 
     /// Interfaces are automatically resolved by the IoC container. 
     /// </summary> 
     /// <param name="dialogs">Interface to dialog service</param> 
     /// <param name="logger">Interface to logger service</param> 
     public MainViewModel(IDialogService dialogs, ILoggerService logger) 
     { 
      _dialogs = dialogs; 
      _logger = logger; 

      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
       _dialogs.ShowMessage("Running in design-time mode!", "Injection Constructor", DialogButton.OK, DialogImage.Information); 
       _logger.WriteLine("Running in design-time mode!"); 
      } 
      else 
      { 
       // Code runs "for real" 
       _dialogs.ShowMessage("Running in run-time mode!", "Injection Constructor", DialogButton.OK, DialogImage.Information); 
       _logger.WriteLine("Running in run-time mode!"); 
      } 
     } 

     public override void Cleanup() 
     { 
      // Clean up if needed 
      _dialogs = null; 
      _logger = null; 

      base.Cleanup(); 
     } 
    } 
} 

그리고 OrderViewModel 클래스 :

using GalaSoft.MvvmLight; 
using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    /// <summary> 
    /// This class contains properties that a View can data bind to. 
    /// <para> 
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. 
    /// </para> 
    /// <para> 
    /// You can also use Blend to data bind with the tool's support. 
    /// </para> 
    /// <para> 
    /// See http://www.galasoft.ch/mvvm/getstarted 
    /// </para> 
    /// </summary> 
    public class OrderViewModel : ViewModelBase 
    { 

     private const string testOrderNumber = "123456"; 
     private Order _order; 

     /// <summary> 
     /// Initializes a new instance of the OrderViewModel class. 
     /// </summary> 
     public OrderViewModel() 
      : this(testOrderNumber) 
     { 

     } 

     /// <summary> 
     /// Initializes a new instance of the OrderViewModel class. 
     /// </summary> 
     public OrderViewModel(string orderNumber) 
     { 
      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
       _order = new Order(orderNumber, "My Company", "Our Address"); 
      } 
      else 
      { 
       _order = GetOrder(orderNumber); 
      } 
     } 

     public override void Cleanup() 
     { 
      // Clean own resources if needed 
      _order = null; 

      base.Cleanup(); 
     } 
    } 
} 

특정하기위한 순서의 뷰를 표시 할 수있는 코드 주문 :

public void ShowOrder(string orderNumber) 
{ 
    // pass the order number to show to ViewModelLocator to be injected 
    //into the constructor of the OrderViewModel instance 
    ViewModelLocator.OrderToShow = orderNumber; 

    View.OrderView orderView = new View.OrderView(); 
} 

이러한 예제는 IoC 아이디어 만 표시하기 위해 제거되었습니다. 많은 시행 착오를 겪었고, 인터넷에서 예제를 검색하고, Unity 2.0 문서가 (이 확장을위한 샘플 코드에서)이 솔루션을 제시하지 못했다는 사실을 알아 냈습니다. 개선 할 수 있다고 생각되면 알려주십시오.

+0

Unity 문서에 구멍이있는 곳을 알고 싶습니다. 거기에 없었던 게 더 있었 니? –

+0

Unity 문서는 꽤 좋았습니다. 2.0 용 샘플 코드 스 니펫을 찾는 데 어려움을 겪었습니다. 1.x에 대한 예제 코드가 많았지 만 많은 부분이 구식이었습니다 (확장을 사용하여 사용할 수있는 새로운 구문이 있었기 때문에이 구문을 사용하지 않는 메시지를 계속 받았습니다). – acordner

+0

처음 게시 한 후 거의 1 년이 지났습니다. 나는 그 당시의 아이디어에 고투하기 시작했습니다. MVVM Light/Unity가 어디까지 갈지 알고 있습니다. – Rod

답변

1

먼저 서비스 위치 패턴 방지 패턴을 피해야합니다.

둘째, OrderView를 가져올 때마다 정적 변수를 설정해야합니까? 그것은 아주 못생긴 디자인입니다.

+0

내가 말했듯이, 나는이 물건에 정말로 새롭고, 단지 내 방식을 느껴 보려고 노력하고있다. 나는 비판뿐만 아니라 그것을 개선하는 방법에 대한 제안에 열려 있습니다. 필자는 아직 MVVM 패턴을 사용하여 완전한 작업용 응용 프로그램을 만들지 않았으며 너무 멀리 떨어지기 전에 최상의 솔루션을 찾고 싶습니다. 경험이 많은 다른 개발자들이 다른 개발자들과 차별화 할 수있는 방법은 개선 기회를 찾는 좋은 방법이라고 생각합니다. 나는 "서비스 로케이터 방지 패턴"을 살펴볼 것입니다. (이 시점에서 그 의미가 무엇인지 전혀 알지 못합니다.) – acordner

+0

OrderView를 가져 오기 전에 정적 변수를 설정하는 것에 동의합니다. 그러나 모든 것을 알아낼 때까지는 훌륭한 해결책이 아닙니다. 매개 변수 재정의 및 DI 기술에 대한 정보를 제공합니다. – acordner

+0

더 나은 솔루션은 주입 할 수있는 추상 팩터 리 패턴입니다. – onof

관련 문제