MVVM命令属性stacktrace
本文关键字:stacktrace 属性 命令 MVVM | 更新日期: 2023-09-27 18:17:25
我想知道在我的ApplicationCommand中使用以下模式执行哪个属性命令,有任何想法吗?今天的日志总是显示ApplicationCommand.Execute(),对跟踪用户操作不是很有用。
类声明:
public class MyViewModel { public ICommand BlinkCommand { get; set; } public ICommand CheckCommand { get; set; } public MyViewModel() { BlinkCommand = new ApplicationCommand(() => DoBlink()); CheckCommand = new ApplicationCommand(() => DoCheck()); } ... }
我的应用程序命令实现的所有命令:
public class ApplicationCommand : RelayCommand
{
public void Execute()
{
// No try-catch, I never code bugs ;o)
Log.Info("Prepare to execute the command " + this);
base.Execute();
Log.Info("Finished to execute the command " + this);
}
}
使用1个命令= 1个类,这很好。使用这种方式,它似乎在WWW上广泛使用,我不知道如何继续:
提前感谢您的帮助
你应该这样重构你的ApplicationCommand
:
public class ApplicationCommand : RelayCommand
{
string commandName;
public void Execute()
{
// No try-catch, I never code bugs ;o)
Log.Info("Prepare to execute the command " + commandName);
base.Execute();
Log.Info("Finished to execute the command " + commandName);
}
public static void SetCommand(MyViewModel vm,
Expression<Func<MyViewModel,ICommand>> commandSelector,
Action action){
var me = commandSelector.Body as MemberExpression;
if(me == null) throw new ArgumentException("Invalid command selector!");
var newCommand = new ApplicationCommand(action);
newCommand.commandName = me.Member.Name;
vm.GetType()
.GetProperty(newCommand.commandName)
.SetValue(vm, newCommand, null);
}
}
//then use it like this
public MyViewModel()
{
ApplicationCommand.SetCommand(this, e => e.BlinkCommand, () => DoBlink());
ApplicationCommand.SetCommand(this, e => e.CheckCommand, () => DoCheck());
}
我知道这是为了调试的目的,所以我们应该打印属性名,然后使用上面的方法更好。
您可以在ApplicationCommand中添加一个额外的实例字符串,该字符串在构造实例时传递,并在调用execute时记录。
public class ApplicationCommand : RelayCommand
{
private string logName;
public ApplicationCommand(Action<T> execute, string logName = "")
{
// ...
this.logName = logName;
}
public void Execute()
{
// No try-catch, I never code bugs ;o)
Log.Info("Prepare to execute the command " + this.logName);
base.Execute();
Log.Info("Finished to execute the command " + this.logName);
}
}
使用它:BlinkCommand = new ApplicationCommand(() => DoBlink(), "Blink");
是否尝试调用GetType()?
public class ApplicationCommand : RelayCommand
{
public ApplicationCommand(Expression<Func<ICommand>> property,Action<T> execute, string logName = "")
{
// ...
this.logName = logName;
}
public void Execute()
{
// No try-catch, I never code bugs ;o)
Log.Info("Prepare to execute the command " + GetTypeName(this.GetType()) + "." + GetPropertyPath(property));
base.Execute();
Log.Info("Finished to execute the command " + GetTypeName(this.GetType()) + "." + GetPropertyPath(property));
}
}
private string GetPropertyPath(LambdaExpression propertyPath, bool acceptsFields = false)
{
Stack<MemberInfo> properties = GetPropertyPathStack(propertyPath, acceptsFields);
return string.Join(".", properties.Select(p => p.Name));
}
private Stack<MemberInfo> GetPropertyPathStack(LambdaExpression propertyPath, bool acceptFields = false)
{
MemberExpression member = propertyPath.Body as MemberExpression;
Stack<MemberInfo> properties = new Stack<MemberInfo>();
while(member != null)
{
if (member.Member is PropertyInfo || (acceptFields && member.Member is FieldInfo))
{
properties.Push(member.Member);
if (member.Expression is MemberExpression)
{
member = member.Expression as MemberExpression;
}
else
{
ConstantExpression constant = member.Expression as ConstantExpression;
member = null;
}
}
else
{
member = null;
}
}
return properties;
}
private string GetTypeName(Type type)
{
if (type.IsGenericType)
{
return GetGenericTypeName(type);
}
else
{
return type.FullName;
}
}
private string GetGenericTypeName(Type type)
{
Type[] genericArguments = type.GetGenericArguments();
string argumentNames = string.Join(", ", genericArguments.Select(GetTypeName));
return string.Format("{0}<{1}>", type.GetBaseName(), argumentNames);
}
希望,这将帮助或激励你更好的解决方案。
用法:
BlinkCommand = new ApplicationCommand(() => BlinkCommand, () => DoBlink());