在尝试获取公共属性的值时,将System.Runtime.Remoting.Proxies.RealProxy与Unit



我正试图将RealProxy与Unity3D一起使用,但我收到了以下错误:

NullReferenceException: Object reference not set to an instance of an object
(wrapper ldfld) System.Object.__ldfld_wrapper_000001804BA82020_System.Single(object,intptr,intptr,intptr)
Player.PlayerController.Setup (UMVC.Core.MVC.Interfaces.IBaseView`1[TModel] view) (at Assets/Player/PlayerController.cs:27)
UMVC.Core.MVC.BaseView`2[TModel,TController].Awake () (at <51bf8ffda04c457aa9f14160e1112cbf>:0)

当我尝试获取PlayerModel的公共成员(如playerModelInstance.jumpPower(时,会引发此错误。

PlayerController.cs背后的代码:

namespace Player
{

public class PlayerController : BaseController<PlayerModel>
{
public override void Setup(IBaseView<PlayerModel> view)
{
base.Setup(view) // you can see the implementation below
// in theory the `Model` is fully initialized after base.Setup(view)
Debug.Log(Model.jumpPower); // THE CODE IS CRASHING HERE
}

} //end PlayerController
}

PlayerModel:

using System;
using UMVC.Core.MVC;
using UnityEngine;
namespace Player
{
[Serializable]
public class PlayerModel : BaseModel
{
public float jumpPower = 12f;

public override void Initialize()
{
base.Initialize();
isOnFieldDidUpdateEnabled = false;
isOnFieldWillUpdateEnabled = false;
}


}
}

ModelProxy:您可以在此处查看实现:UMVC.Core/MVC/ModelProxy.cs

BaseModel:

其继承自CCD_ 7以使RealProxy工作

基本控制器

using UMVC.Core.MVC.Interfaces;
namespace UMVC.Core.MVC
{
public abstract class BaseController<TModel> where TModel : BaseModel
{
protected TModel Model { get; set; }
protected IBaseView<TModel> View;
protected ModelProxy<TModel> ModelProxy;
public virtual void Setup(IBaseView<TModel> view)
{
View = view;
ModelProxy<TModel> modelProxy = ModelProxy<TModel>.Bind(View.GetModel());
Model = modelProxy.GetTransparentProxy();
Model.Initialize();
ModelProxy = modelProxy;
SubscribeEvents();
}
public virtual void LateSetup()
{
}
protected virtual void SubscribeEvents()
{
ModelProxy.OnFieldWillUpdate += View.OnFieldWillUpdate;
ModelProxy.OnFieldDidUpdate += View.OnFieldDidUpdate;
}

}
}
namespace UMVC.Core.MVC
{
[Serializable]
// MarshalByRefObject are necessary in order to RealProxy be able to work
public abstract class BaseModel : MarshalByRefObject, IBaseModel
{
public bool isOnFieldWillUpdateEnabled = true;
public bool isOnFieldDidUpdateEnabled = true;

public virtual void Initialize()
{
}

}
}

注意:ModelProxy在Unity项目之外工作,因为单元测试涵盖了此代码,可以从UMVC.Core/Tests/MVCTests.cs.中看到

编辑1:

Debug.Log(Model.jumpPower);更改为Debug.Log(Model);输出

Player.PlayerModel
UnityEngine.Debug:Log(Object)
Player.PlayerController:Setup(IBaseView`1) (at Assets/Player/PlayerController.cs:27)
UMVC.Core.MVC.BaseView`2:Awake()

因此,似乎Model已正确安装,但我无法访问我的公众成员。

作为RealProxy的替代品,我使用了类似于microsoftINotifyPropertyChanged:的模式

public interface INotifyPropertyChanged
{
event Delegates.OnFieldWillUpdate OnFieldWillUpdate;
event Delegates.OnFieldDidUpdate OnFieldDidUpdate;
}

修改我的BaseModel如下:

[Serializable]
public abstract class BaseModel: IBaseModel, INotifyPropertyChanged {
public bool isOnFieldWillUpdateEnabled = true;
public bool isOnFieldDidUpdateEnabled = true;
public virtual event Delegates.OnFieldWillUpdate OnFieldWillUpdate;
public virtual event Delegates.OnFieldDidUpdate OnFieldDidUpdate;
public virtual void Initialize() {}
protected virtual void RaiseOnFieldWillUpdate<T>(T newValue, [CallerMemberName] string propertyName = null) {
var eventArgs = new PropertyChangedEventArgs(propertyName);
object oldValue;
var type = GetType();
var field = type.GetField(eventArgs.PropertyName);
if (field != null) {
oldValue = field.GetValue(this);
}
else {
oldValue = type.GetProperty(eventArgs.PropertyName) ? .GetValue(this);
}
OnFieldWillUpdate?.Invoke(this, newValue, oldValue, eventArgs);
}
protected virtual void RaiseOnFieldDidUpdate<T>(T newValue, [CallerMemberName] string propertyName = null) {
OnFieldDidUpdate?.Invoke(this, newValue, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool Set<T>(ref T field, T value, Expression<Func<T>> property) {
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
string propertyName = ((MemberExpression) property.Body).Member.Name;
if (isOnFieldWillUpdateEnabled) RaiseOnFieldWillUpdate(value, propertyName);
field = value;
if (isOnFieldDidUpdateEnabled) RaiseOnFieldDidUpdate(field, propertyName);
return true;
}
}

这样使用:

[Serializable]
public class MvcModel: BaseModel 
{
[SerializeField] private int val;
public int Value {
get => val;
set => Set(ref val, value, () => Value);
}
}

相关内容

最新更新