使用Unity IoC容器的更智能的DTO

时间:2015-12-08 13:25:33

标签: c# wpf mvvm unity-container

我有一个MVVM模型,我的视图模型包含observableCollection<RfidData>。 每当更新此数据时,我想在属性上调用RaisePropertyChanged()

我在某处看到它可以用Unity IoC容器非常巧妙地完成,但我再也找不到了。

这是我的班级:

public class RfidData : INotifyPropertyChanged
{
    private bool _checkedIn = false;
    private Guid _id;
    private int _collectorId;
    private DateTime _checkInTime;
    private string _name = "Test Name";

    public bool CheckedIn
    {
        get { return _checkedIn; }
        set { _checkedIn = value; RaisePropertyChanged(); }
    }

    public Guid Id
    {
        get {return _id;}
        set { _id = value; RaisePropertyChanged(); }
    }

    public int CollectorId
    {
        set { _collectorId = value; RaisePropertyChanged(); }
        get { return _collectorId; }
    }

    public DateTime CheckInTime
    {
        set { _checkInTime = value; RaisePropertyChanged(); }
        get { return _checkInTime; }
    }

    public string Name
    {
        set { _name = value; RaisePropertyChanged(); }
        get { return _name; }
    }

    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

我认为你正在寻找拦截器。这是一个如何使用它的例子 Unity Interceptor

答案 1 :(得分:0)

对我有用的解决方案:

使用 export DPDK_BUILD=$DPDK_DIR/x86_64-native-linuxapp-gcc/ ./configure --with-dpdk=$DPDK_BUILD make make install 属性定义类:

virtual

public class RfidData : BaseViewModel { public RfidData(Guid id) { Id = id; } public virtual int CollectorId { get; set; } public virtual DateTime CheckInTime { get; set; } public virtual string Name { get; set; } public virtual bool CheckedIn { get; set; } public virtual DateTime TimeStamp { get; set; } public virtual Guid Id { get; } } 将执行RaidPropertyChange()方法:

BaseViewModel

@bilpor's link.创建几乎 rip-off 调用的方法因调用public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } 而不是旧RaisePropertyChanged而不同。 我相信使用像PropertyChanged这样的新方法会有所改善,但我还没有调查过它。

[CallerMemberName]

最后,使用Unity Intercepter类注册类using System; using System.ComponentModel; using System.Reflection; using Microsoft.Practices.Unity.InterceptionExtension; public class PropertyChangedCallHandler : ICallHandler { public int Order { get; set; } public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { //Only if not same value as current, and it's a 'set' called var shouldRaise = ShouldRaiseEvent(input); var res = getNext()(input, getNext); if (res.Exception == null && shouldRaise) RaiseEvent(input); return res; } private bool ShouldRaiseEvent(IMethodInvocation input) { var methodBase = input.MethodBase; //Is the method a property setter? if (!methodBase.IsSpecialName || !methodBase.Name.StartsWith("set_")) { return false; } //Get the name of the property out so we can use it to raise a //property changed event string propertyName = methodBase.Name.Substring(4); //Retrieve the property getter PropertyInfo property = methodBase.ReflectedType.GetProperty(propertyName); MethodInfo getMethod = property.GetGetMethod(); //IF the property has no get method, we don't care if (getMethod == null) { return false; } //Get the current value out object oldValue = getMethod.Invoke(input.Target, null); //Get the updated value object value = input.Arguments[0]; //Is the new value null? if (value != null) { //Is the new value different from the old value? if (value.Equals(oldValue) == false) { return true; } } else { //Is the new value (null) different from the //old value (non-null)? if (value != oldValue) { return true; } } return false; } private void RaiseEvent(IMethodInvocation input) { FieldInfo field = null; //Get a reference to the PropertyChanged event out of the current //type or one of the base types var type = input.MethodBase.ReflectedType; while (field == null && type != null) { //This differs from the original field = type.GetField("RaisePropertyChanged", BindingFlags.Instance | BindingFlags.NonPublic); type = type.BaseType; } //If we found the PropertyChanged event if (field != null) { //Get the event handler if there is one var evt = field.GetValue(input.Target) as MulticastDelegate; if (evt != null) { //Get the property name out string propertyName = input.MethodBase.Name.Substring(4); //Invoke the property changed event handlers evt.DynamicInvoke(input.Target, new PropertyChangedEventArgs(propertyName)); } } } }

RfidData
但是,奇怪的是: 实例化时,通常是var notificationPolicy = _container.AddNewExtension<Interception>() .RegisterType<BaseViewModel, RfidData>() .Configure<Interception>() .SetDefaultInterceptorFor(userControlType, new VirtualMethodInterceptor()) .AddPolicy("NotificationPolicy"); notificationPolicy.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set)); notificationPolicy.AddCallHandler<PropertyChangedCallHandler>(); ,但我通过contain.Resolve<RfidData>()方法获取所有数据。 但它接受正确的类型。