代码之家  ›  专栏  ›  技术社区  ›  Olivier Pons

如何制作此系统。可序列化类不可知?

  •  3
  • Olivier Pons  · 技术社区  · 7 年前

    原则如下:

    • 我有很多Ajax交换
    • 我有一个 System.Serializable 类是Ajax调用的结果
    • 我总是有两个功能:
      • 调用的函数
      • 分析调用的函数

    进行调用的函数获取一个回调作为参数,进行调用,完成后,使用 系统可序列化

    下面是一个示例:

    [System.Serializable]
    public class JsonState
    {
        public int state;
        public string message;
        public JsonData data;
    }
    

    在我的课堂上:

    public class DataController : MonoBehaviour {
        public delegate void CallbackAjaxStateFinished(JsonState j);
        public CallbackAjaxStateFinished cbAjaxStateFinished = null;
    
        public void AjaxStateGet(CallbackAjaxStateFinished cb=null)
        {
            /* make the Ajax call*/
            cbAjaxStateFinished = cb;
            new HTTPRequest(
                new Uri(baseURL + _urlGetState),
                HTTPMethods.Get, AjaxStateGetFinished
            ).Send();
        }
    
        private void AjaxStateGetFinished(
            HTTPRequest request, HTTPResponse response
        ) {
            if (response == null) {
                return;
            }
            JsonState j = null;
            try {
                j = JsonUtility.FromJson<JsonState>(response.DataAsText);
                if (cbAjaxStateFinished != null) {
                    cbAjaxStateFinished(j);
                }
            } catch (ArgumentException) { /* Conversion problem */
                TryDisplayFatalError(FatalErrors[FatalError.ConversionProblem2]);
            }
        }
    }
    

    问题是,我已经有了3个这样的Ajax调用,始终遵循相同的原则,下面是3个回调,让您概括一下:

    public CallbackAjaxStateFinished cbAjaxStateFinished = null;
    public CallbackAjaxGamesToJoinFinished cbAjaxGamesToJoinFinished = null;
    public CallbackAjaxGameDetailFinished cbAjaxGameDetailFinished = null;
    

    但我将添加另一个,并复制/粘贴代码以发送/接收上述内容,只需进行2个小修改:

    • 更改 CallbackXxx 类型
    • 更改 系统可序列化

    我是C#新手,有没有办法让这个通用?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Olivier Pons    7 年前

    这个过程并没有那么复杂,假设您的回调总是这样 void(SomeStateclass) .

    更换 JSonState 在上面的代码中使用泛型T可以实现这一目的。这就是你最终的结果:

    // The DataController takes a generic T respresenting one of your State classes
    // notice that we need a constraint for the type T to have a parameterless constructor
    public class DataController<T> : MonoBehaviour where T: new()
    { 
        // the delegate takes the generic type, so we only need one
        public delegate void CallbackAjaxFinished(T j);
    
        public CallbackAjaxFinished cbAjaxFinished = null;
    
        public void AjaxStateGet(CallbackAjaxFinished cb=null)
        {
            /* make the Ajax call*/
            cbAjaxFinished = cb;
            new HTTPRequest(
                new Uri(baseURL + _urlGetState),
                HTTPMethods.Get, AjaxStateGetFinished
            ).Send();
        }
    
        private void AjaxStateGetFinished(
            HTTPRequest request, HTTPResponse response
        ) {
            if (response == null) {
                return;
            }
            // here we use the default keyword to get 
            // an instance of an initialized stronglytyped T
            T j = default(T);
            try {
                // the T goes into the FromJson call as that one was already generic
                j = JsonUtility.FromJson<T>(response.DataAsText);
                if (cbAjaxFinished != null) {
                    cbAjaxFinished(j);
                }
            } catch (ArgumentException) { /* Conversion problem */
                TryDisplayFatalError(FatalErrors[FatalError.ConversionProblem2]);
            }
        }
    }
    

    仅此而已。您的datacontroller类现在是泛型的。

    您可以这样使用它:

    var dc = new DataController<JsonState>()
    dc.AjaxStateGet( (v) => {
       v.Dump("jsonstate");
    });
    
    var dc2 = new DataController<JsonState2>();
    dc2.AjaxStateGet( (v) => {
       v.Dump("jsonstate2");
    });