我有一个名为IMailSender和ISMSSender的接口。我有一个名为Device的抽象类。
Device1继承自Device,IMailSender Device2继承自Device,IMailSender,ISMSSender
我希望IMailSender的所有字段都调用notifypropertychanged。我是否必须在Device1中实现所有的IMailSender属性来调用notifypropertychanged并在Device2中执行相同的代码,或者有更好的解决方案?
谢谢。
发布于 2013-02-18 19:08:35
您的类必须引发PropertyChanged事件,因为接口只会确保所有实现类都有一个具有相同返回类型的方法。一个好的方法是定义一个基类(这是MVVM模式的一个非常常见的方法,例如MVVM Light框架),它通过一个方法引发事件,所有其他合适的类都可以从这个方法继承。例如:
...
public abstract class BaseViewModel : IMailSender, INotifyPropertyChanged
{
...
public void RaisePropertyChanged(string property)
{
if (property != null)
{
PropertyChanged(property);
}
}
}继承类可以使用它,如下所示:
...
public class AViewModel : BaseViewModel
{
...
private string _property;
public string Property
{
get
{
return _property;
}
set
{
_property = value;
RaisePropertyChanged("Property");
}
}
...
}发布于 2013-02-18 21:27:39
另一种解决方案是面向方面的。例如,使用postsharp。s. http://www.sharpcrafters.com/solutions/notifypropertychanged
因此,您可以在该属性上放置PropertyChanged属性。
同样,在.net 4.5中,您可以使用CallerInfoAttribute来实现一个不需要属性名称的简单实现,例如,参见:
http://danrigby.com/2012/04/01/inotifypropertychanged-the-net-4-5-way-revisited/ ->
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}这样,您就可以在不使用任何参数的情况下调用该方法
public int MyProperty
{
get
{
...
}
set
{
m_MyProperty=value;
OnPropertyChanged();
}
}发布于 2014-03-16 00:12:06
使用它,调用ObservableFactory.Create()并使用返回对象。要使用notify事件,只需将其强制转换为INotifyPropertyChanged
public static class ObservableFactory
{
public static T Create<T>(T target)
{
if (!typeof(T).IsInterface)
throw new ArgumentException("Target should be an interface", "target");
var proxy = new Observable<T>(target);
return (T)proxy.GetTransparentProxy();
}
}
internal class Observable<T> : RealProxy, INotifyPropertyChanged, INotifyPropertyChanging
{
private readonly T target;
internal Observable(T target)
: base(ImplementINotify(typeof(T)))
{
this.target = target;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
if (methodCall != null)
{
return HandleMethodCall(methodCall);
}
return null;
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
IMessage HandleMethodCall(IMethodCallMessage methodCall)
{
var isPropertySetterCall = methodCall.MethodName.StartsWith("set_");
var propertyName = isPropertySetterCall ? methodCall.MethodName.Substring(4) : null;
if (isPropertySetterCall)
{
OnPropertyChanging(propertyName);
}
try
{
object methodCalltarget = target;
if (methodCall.MethodName == "add_PropertyChanged" || methodCall.MethodName == "remove_PropertyChanged"||
methodCall.MethodName == "add_PropertyChanging" || methodCall.MethodName == "remove_PropertyChanging")
{
methodCalltarget = this;
}
var result = methodCall.MethodBase.Invoke(methodCalltarget, methodCall.InArgs);
if (isPropertySetterCall)
{
OnPropertyChanged(methodCall.MethodName.Substring(4));
}
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
catch (TargetInvocationException invocationException)
{
var exception = invocationException.InnerException;
return new ReturnMessage(exception, methodCall);
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanging(string propertyName)
{
var handler = PropertyChanging;
if (handler != null) handler(this, new PropertyChangingEventArgs(propertyName));
}
public static Type ImplementINotify(Type objectType)
{
var tempAssemblyName = new AssemblyName(Guid.NewGuid().ToString());
var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
tempAssemblyName, AssemblyBuilderAccess.RunAndCollect);
var moduleBuilder = dynamicAssembly.DefineDynamicModule(
tempAssemblyName.Name,
tempAssemblyName + ".dll");
var typeBuilder = moduleBuilder.DefineType(
objectType.FullName, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
typeBuilder.AddInterfaceImplementation(objectType);
typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanged));
typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanging));
var newType = typeBuilder.CreateType();
return newType;
}
}https://stackoverflow.com/questions/14809637
复制相似问题