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上广泛使用,我不知道如何继续:

提前感谢您的帮助

MVVM命令属性stacktrace

你应该这样重构你的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());