这不仅仅是一个问题的评论,尽管反馈会很好。我的任务是为我们正在进行的新项目创建用户界面。我们想要使用WPF,并且我想了解所有现有的可用UI设计技术。由于我对WPF相当陌生,我一直在研究可用的东西。我想我使用MVVM Light Toolkit的主要原因在于它的“Blendability”和EventToCommand行为!),但我也希望将IoC也纳入其中。所以,这就是我所提出的。我修改了MVVM 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文档缺乏(在示例代码中用于扩展)以提出该解决方案。如果您认为可以改进,请告诉我。
我很想知道你觉得Unity文档中有什么漏洞。你还需要什么呢? – 2010-12-23 04:46:31
Unity文档非常好,我只是很难找到2.0版的任何示例代码片段,尤其是使用扩展。 1.x有很多示例代码,但很多都是过时的(我不断收到消息,不使用该语法来做事情,因为使用扩展可以使用新的语法)。 – acordner 2010-12-30 17:27:01