简体   繁体   English

基类构造函数中Call abstract方法的替代方法

[英]Alternative to Call abstract method in base class constructor

my problem is this: 我的问题是这样的:

I Have a base class 我有一个基础课

public abstract class ViewModelBase 

wich contains an abstract method "RegisterCommands" 其中包含抽象方法“ RegisterCommands”

protected abstract void RegisterCommands();

All my Derived classes must, obviously, implements this method, for example my LoginViewModel has 很显然,我所有的派生类都必须实现此方法,例如我的LoginViewModel具有

protected override void RegisterCommands()
{
    LoginCommand?
        .Configure(
            execute: (msg) => { Login(User); },
            canExecute: (x) => { return CanLogin(); }
            );
}

and call it when class is instantiated, but i don't want call this method in every derived class constructor (if I have 100 derived classes i must call RegisterCommand 100 times). 并在实例化类时调用它,但是我不想在每个派生类构造函数中调用此方法(如果我有100个派生类,我必须调用RegisterCommand 100次)。

Normal solution is call RegisterCommand in the base class constructor 正常的解决方案是在基类构造函数中调用RegisterCommand

protected abstract void RegisterCommands();

public ViewModelBase()
{
    RegisterCommands();
}

and this usually works (even if I do not know if it's a good practice) but...but... 这通常是可行的(即使我不知道这是否是个好习惯),但是...但是...

in my scenario, in all the RegisterCommands methods I use my ICustomCommand objects, which are initialized in the derived class constructor with dependency injection 在我的场景中,在所有RegisterCommands方法中,我都使用ICustomCommand对象,这些对象在依赖项注入的派生类构造函数中初始化

public class LoginViewModel : ViewModelBase
{

    private ICustomCommand _loginCommand;

    public ICustomCommand LoginCommand
    {
        get
        {
            return _loginCommand;
        }
        set
        {
            _loginCommand = value;
        }
    }

    public LoginViewModel(ICustomCommand loginCommand)
    {
        _loginCommand = loginCommand;
    }

    protected override void RegisterCommands()
    {
        LoginCommand?
            .Configure(
                execute: (msg) => { Login(User); },
                canExecute: (x) => { return CanLogin(); }
                );
    }

So, because base class constructor is called before derived class constructor, i can't call RegisterCommands() in base class constructor (because my ICustomCommands are not initialized yet in derived class so RegisterCommands() try to use my ICustomCommand which are still null). 因此,由于基类构造函数在派生类构造函数之前被调用,因此我无法在基类构造函数中调用RegisterCommands()(因为我的ICustomCommands尚未在派生类中初始化,因此RegisterCommands()尝试使用仍为null的ICustomCommand) 。

I know that is not possible call derived class constuctor before base class constructor, so what could be a valid, simple and clean solution to call RegisterCommands in all derived class calling this command in only one point? 我知道不可能在基类构造函数之前调用派生类构造函数,那么在仅一处调用此命令的所有派生类中调用RegisterCommands的有效,简单,简洁的解决方案是什么?

thanks for answer 谢谢你的回答

UPDATE: 更新:

As I said, RegisterCommands() is plural because every derived class could have N ICustomCommand objects 如我所说,RegisterCommands()是复数的,因为每个派生类都可以有N个ICustomCommand对象

So i can have 所以我可以有

LoginCommand for my LoginViewModel 我的LoginViewModel的LoginCommand

SaveCommand, DeleteCommand for another ViewModel SaveCommand,另一个ViewModel的DeleteCommand

etc. 等等

One solution I think now is to remove ICustomCommand initalization from constructor and resolve it "on the fly" in getter property trough a static Resolver class, something like this 我现在认为的一种解决方案是从构造函数中删除ICustomCommand初始化并通过静态Resolver类在getter属性中“即时”解决它。

public ICustomCommand LoginCommand
{
    get
    {
        if(_loginCommand == null)
            MyStaticResolver.Resolve<ICustomCommand>();
        return _loginCommand;

But I'm still not convinced 但我仍然不相信

If you use interfaces to represent your commands, you could pass them to the base class and expose a method to retrieve the commands. 如果使用接口表示命令,则可以将它们传递给基类,并公开一种方法来检索命令。 Your Registration method can then use them as needed: 然后,您的注册方法可以根据需要使用它们:

public abstract class ViewModelBase
{
    public ViewModelBase(params ICustomCommand[] commands)
    {
        _commands = commands;            
        RegisterCommands();
    }

    private IEnumerable<ICustomCommand> _commands;

    protected abstract void RegisterCommands();

    //This method gets you the commands
    protected T GetCommand<T>() where T : ICustomCommand
    {
        var command = _commands.FirstOrDefault(c => typeof(T).IsAssignableFrom(c.GetType()));
        return (T)command ;
    }
}

public class LoginViewModel : ViewModelBase
{
    public LoginViewModel(ILoginCommand command):base(command)
    {

    }

    protected override void RegisterCommands()
    {
        //Get the command from the base class
        var command = GetCommand<ILoginCommand>();
        command?
        .Configure(
            execute: (msg) => { Login(User); },
            canExecute: (x) => { return CanLogin(); }
            );
    }
}

public class LoginCommand : ILoginCommand
{
}

public interface ILoginCommand : ICustomCommand
{
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM