MVVM 命令 属性 堆栈跟踪

MVVM Command property stacktrace

我想知道在我的 ApplicationCommand 中使用以下模式执行了哪个 属性 命令,知道吗?今天日志总是显示 ApplicationCommand.Execute(),对跟踪用户操作不是很有用。

Class 声明:

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个命令=1class,没问题。使用这种方式,似乎在WWW上被广泛使用,我不知道如何进行:(

预先感谢您的帮助

您尝试调用 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());

您可以将额外的实例字符串添加到您在构造实例时传递的 ApplicationCommand,并在调用执行时记录该字符串。

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");

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

我知道这是为了调试目的,所以我们应该打印 属性 名称,然后使用上面的方法更好。