C# 如何使用zenject将MonoBehavior类注入Unity3d中的非MonoBehavior?

C# 如何使用zenject将MonoBehavior类注入Unity3d中的非MonoBehavior?,c#,unity3d,dependency-injection,zenject,C#,Unity3d,Dependency Injection,Zenject,我想尽可能地组织代码,但我在组织代码时遇到了一些问题。我试图使用坚实的原则,并使单独的实体。我想使用MVVM查看()和DI容器() 这是我的第一个项目,我正在尝试组织代码 我的问题是如何使用来自GameInstaller类的zenject容器将LoginViewModel作为静态类注入LoginController [Binding] public class LoginViewModel : MonoBehaviour, INotifyPropertyChanged { privat

我想尽可能地组织代码,但我在组织代码时遇到了一些问题。我试图使用坚实的原则,并使单独的实体。我想使用MVVM查看()和DI容器()

这是我的第一个项目,我正在尝试组织代码

我的问题是如何使用来自
GameInstaller
类的zenject容器将
LoginViewModel
作为静态类注入
LoginController

[Binding]
public class LoginViewModel : MonoBehaviour, INotifyPropertyChanged
{

    private string _username = "";
    private string _passsword = "";
    private string _errorMessage = "";
    private bool _autologin = false;

    [Inject]
    private LoginController _loginController;

    [Binding]
    public string Username {
        get
        {
            return _username;
        }
        set
        {
            if (_username == value)
            {
                return; // No change.
            }

            _username = value;
            Debug.Log($"SET username: {value}");
            OnPropertyChanged("Username");
        }
    }

    [Binding]
    public string Password {
        get
        {
            return _passsword;
        }
        set
        {
            if (_passsword == value)
            {
                return; // No change.
            }

            _passsword = value;
            Debug.Log($"SET password: {value}");
            OnPropertyChanged("Password");
        }
    }

    [Binding]
    public bool Autologin {
        get
        {
            return _autologin;
        }
        set
        {
            if (_autologin == value)
            {
                return; // No change.
            }

            _autologin = value;
            Debug.Log($"SET autologin: {value}");
            OnPropertyChanged("Autologin");
        }
    }

    [Binding]
    public void LoginButtonClick()
    {
        Debug.Log("LoginButtonClick");

        _loginController.Login(this);
        //ErrorMessage = "blabla";
    }

    [Binding]
    public string ErrorMessage
    {
        get
        {
            return _errorMessage;
        }
        set
        {
            if (_errorMessage == value)
            {
                return; // No change.
            }

            _errorMessage = value;
            Debug.Log($"SET errorMessage: {value}");
            OnPropertyChanged("ErrorMessage");
        }
    }

    /// <summary>
    /// Event to raise when a property's value has changed.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class LoginController
{
    private readonly ApiController _apiController;

    [Inject]
    private readonly LoginViewModel _loginViewModel;

    public LoginController(ApiController apiController)
    {
        _apiController = apiController;
    }

    public void Login(LoginViewModel loginViewModel)
    {
        try
        {
            string userJson = _apiController.PostLogin(loginViewModel.Username);

            _loginViewModel.ErrorMessage = "bla bla trololo";
            Debug.Log(userJson);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

public class GameInstaller : MonoInstaller
{
    [Inject]
    Settings _settings = null;

    public override void InstallBindings()
    {
        InstallViewModels();
        InstallServices();
        InstallSignals();
        InstallControllers();
    }

    private void InstallViewModels()
    {
        Container.Bind<LoginViewModel>().AsSingle();
    }

    private void InstallControllers()
    {
        Container.Bind<LoginController>().AsSingle().NonLazy();
        Container.Bind<ApiController>().AsSingle().NonLazy();
    }

    private void InstallServices()
    {
    }

    private void InstallSignals()
    {
    }

    [Serializable]
    public class Settings
    {
    }
}
[绑定]
公共类LoginView模型:MonoBehavior,INotifyPropertyChanged
{
私有字符串_username=“”;
私有字符串_passswill=“”;
私有字符串_errorMessage=“”;
private bool_autologin=假;
[注入]
私人登录控制器(LoginController);;
[有约束力]
公共字符串用户名{
得到
{
返回_用户名;
}
设置
{
如果(_username==值)
{
return;//没有变化。
}
_用户名=值;
Log($“设置用户名:{value}”);
OnPropertyChanged(“用户名”);
}
}
[有约束力]
公共字符串密码{
得到
{
回归;;
}
设置
{
如果(_passswill==值)
{
return;//没有变化。
}
_密码=价值;
Log($“设置密码:{value}”);
OnPropertyChanged(“密码”);
}
}
[有约束力]
公共图书馆{
得到
{
返回自动登录;
}
设置
{
如果(_autologin==值)
{
return;//没有变化。
}
_autologin=值;
Log($“SET autologin:{value}”);
OnPropertyChanged(“Autologin”);
}
}
[有约束力]
public void LoginButtonClick()
{
Log(“LoginButtonClick”);
_loginController.Login(此);
//ErrorMessage=“blabla”;
}
[有约束力]
公共字符串错误消息
{
得到
{
返回错误消息;
}
设置
{
如果(_errorMessage==值)
{
return;//没有变化。
}
_errorMessage=值;
Log($“SET errorMessage:{value}”);
OnPropertyChanged(“错误消息”);
}
}
/// 
///属性值更改时引发的事件。
/// 
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
公共类登录控制器
{
专用只读ApiController\u ApiController;
[注入]
私有只读LoginViewModel _LoginViewModel;
公共登录控制器(ApiController ApiController)
{
_apiController=apiController;
}
公共无效登录(LoginViewModel LoginViewModel)
{
尝试
{
字符串userJson=_apiController.PostLogin(loginViewModel.Username);
_loginViewModel.ErrorMessage=“bla bla trololo”;
Log(userJson);
}
捕获(例外情况除外)
{
掷骰子;
}
}
}
公共类游戏安装程序:MonoInstaller
{
[注入]
设置_Settings=null;
public override void InstallBindings()
{
InstallViewModels();
InstallServices();
安装信号();
安装控制器();
}
私有void InstallViewModels()
{
Container.Bind().AsSingle();
}
私有void InstallControllers()
{
Container.Bind().AsSingle().NonLazy();
Container.Bind().AsSingle().NonLazy();
}
专用服务()
{
}
专用信号()
{
}
[可序列化]
公共类设置
{
}
}
让我们从这里开始:

ViewModel(或VM)保存将在视图上显示的数据。它包含可以绑定到视图元素的所有属性。所有视图模型都继承自INotifyPropertyChanged,当数据更改和UI元素需要更新时,INotifyPropertyChanged会向系统发出警报

由于ViewModel本质上是一个简单的对象而不是一个服务,我认为它不需要被注入任何地方

您可以做的是注入一个
工厂
,并从中获取ViewModel

在代码中,您试图将控制器注入ViewModel,而不是相反