首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在尝试获取公共属性的值时,将System.Runtime.Remoting.Proxies.RealProxy与Unity一起使用会引发问题

在尝试获取公共属性的值时,将System.Runtime.Remoting.Proxies.RealProxy与Unity一起使用会引发问题
EN

Stack Overflow用户
提问于 2020-07-08 16:52:31
回答 1查看 483关注 0票数 1

我试图将RealProxy与Unity3D一起使用,并得到了以下错误:

代码语言:javascript
复制
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**:**背后的代码

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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;
        }


    }
}
代码语言:javascript
复制
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);输出

代码语言:javascript
复制
Player.PlayerModel
UnityEngine.Debug:Log(Object)
Player.PlayerController:Setup(IBaseView`1) (at Assets/Player/PlayerController.cs:27)
UMVC.Core.MVC.BaseView`2:Awake()

因此,Model似乎是正确实例化的,但我无法访问我的公共成员。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-13 12:06:08

作为RealProxy的替代品,我使用了类似microsoft INotifyPropertyChanged这样的模式。

代码语言:javascript
复制
public interface INotifyPropertyChanged
{
   event Delegates.OnFieldWillUpdate OnFieldWillUpdate;
   event Delegates.OnFieldDidUpdate OnFieldDidUpdate;
}

修改了我的BaseModel如下:

代码语言:javascript
复制
[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;
    }

}

像这样使用它:

代码语言:javascript
复制
[Serializable]
public class MvcModel: BaseModel 
{

   [SerializeField] private int val;

    public int Value {
        get => val;
        set => Set(ref val, value, () => Value);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62799731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档