这更像是一篇评论而非问题,但反馈将是很好的。我被指派为我们正在进行的一个新项目创建用户界面。我们想要使用WPF,并且我想了解所有现代UI设计技术。由于我对WPF还比较陌生,所以一直在研究可以使用的技术。我认为我已经基本确定使用MVVM Light Toolkit(主要因为它的"可混合性"和EventToCommand行为!),但我也想结合IoC一起使用。所以,这就是我想到的。我修改了MVVM Light项目中默认的ViewModelLocator类,使用UnityContainer来处理依赖注入。考虑到3个月前我连90%的这些术语都不知道,我想我正在正确的道路上。
// 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文档缺乏(扩展示例代码),请让我知道您是否认为它可以改进。