我试图将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**](https://github.com/loic-lopez/UMVC/blob/master/UMVC.Core/MVC/ModelProxy.cs)
BaseModel
它是从MarshalByRefObject 继承而来的,以使RealProxy工作在上。
BaseController
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在团结项目之外工作,因为单元测试涵盖了从核心/测试/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似乎是正确实例化的,但我无法访问我的公共成员。
发布于 2020-07-13 12:06:08
作为RealProxy的替代品,我使用了类似microsoft INotifyPropertyChanged这样的模式。
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);
}
}https://stackoverflow.com/questions/62799731
复制相似问题