如何检查参数类型?

时间:2017-12-22 06:48:30

标签: c# unity3d

我已经制作了自己的Ajax" generic" (不记得你在C#中如何称呼这个原则)就像这样(只有相关的函数):

public class Ajax<T> 
{
    public delegate void CallbackAjaxFinished(T j);
    public void Get(string Url, CallbackAjaxFinished cbAjaxFinished)
    {
        /* blablah launch the Ajax call which calls back GetFinished() below */
    }
    private void GetFinished(HTTPRequest request, HTTPResponse response)
    {
        ConvertThenCallback(response, true);
    }
    private void ConvertThenCallback(HTTPResponse response, bool isGet)
    {
        try {
            /* make conversion, T could be for example class JsonData */
            j = (T)JsonUtility.FromJson<T>(response.DataAsText);
        } catch (ArgumentException) { /* Conversion problem */
            return;
        }
    }
}

这很好用,就像这样:

Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
    baseURL + _urlGetState, /* get Url */
    /* callback Ajax finished: */
    (JsonState j) => { /* do stuff in the callback */ }
);

问题是Unity的JsonUtility没有处理嵌套数组(...)。

长话短说,我喜欢我的&#34;泛型&#34;东西,传递自定义&#34; json解码&#34;函数回调,默认= null,在ConvertThenCallback()函数中,执行以下操作:

  • 如果没有自定义功能,请拨打j = (T)JsonUtility.FromJson<T>(response.DataAsText);(就像现在一样)
  • 如果有自定义功能,请拨打j = (T)callback(response.DataAsText);
  • 之类的内容

你会如何在C#中做到这一点?

更新

这是我的JsonState +依赖声明:

[System.Serializable]
public class JsonGameDataCell
{
    public JsonGameDataBoatCurrentPlayerShot[] c;
    public JsonGameDataBoatOpponentShot[] o;
}

[System.Serializable]
public class JsonGameData
{
    public JsonGameDataStart start;
    public JsonGameDataCell[][] board;
}

[System.Serializable]
public class JsonData
{
    public string player;
    public JsonGameData game;
}

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

我的实际问题是Unity Json实用程序无法解码嵌套数组,因此当我调用JsonGameDataCell[][] board时,属性null始终设置为JsonUtility.FromJson() 。所以我必须实现自己的Json解码器。我会使用效果很好的SimpleJSON,但我只想在特定情况下使用此解码器

1 个答案:

答案 0 :(得分:1)

在我看来,你正在寻找一种叫做interface的东西。您可以使用它们来标记某些对象,以便应用程序“知道”如何对待它们。

您可以这样创建interface

public interface ICustomJson
{
    void FromJson(string jsonString);
}

现在在ConvertAndCallback,您可以查看if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))

如果是,您只需创建一个已转换为ICustomJson的类的实例,然后调用FromJson(string)方法。

请记住,您的对象没有默认(无参数)构造函数,因此您可以创建该类的未初始化版本。

示例ConvertAndCallback

T result = null;
if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))
{
    result = (T)FormatterServices.GetUninitializedObject(typeof(T));
    ((ICustomJson)result).FromJson(string);
}
else
{
    result = (T)JsonUtility.FromJson<T>(response.DataAsText);
}

另一个解决方案是(再次)使用interface但仅用于反序列化器部分。这将涉及另一个类(或工厂)为指定类型生成反序列化器。

您可以使用IJsonSerializerT Deserialize(string)中的两种方法创建名为string Serialize(T)的界面:

public interface IJsonSerializer<T>
{
    T Deserialize(string jsonString);
    string Serialize(T jsonObject);
}

现在有了这个界面,创建一个实现这个

的类
public class JsonStateSerializer : IJsonSerializer<JsonState>
{
    public JsonState Deserialize(string jsonString)
    {
        // put your deserialization code up in here
    }

    public string Serialize(JsonState jsonObject)
    {
        // put your serialization code up in here
    }
}

现在创建默认值:

public class DefaultJsonSerializer<T> : IJsonSerializer<T>
{
    public T Deserialize(string jsonString)
    {
        return (T)JsonUtility.FromJson<T>(jsonString);
    }

    public string Serialize(T jsonObject)
    {
        return JsonUtility.ToJson(jsonObject);
    }
}

拥有这两个将更容易区分在ConvertAndCallback方法中稍后使用哪一个。

现在,如果您需要,可以创建一些Attribute来标记将哪个序列化程序应用于哪个对象或使用某些工厂。

我将使用最简单的方法,只需修改ConvertAndCallback方法,以便它有另一个(可选)参数。

void ConvertThenCallback(HTTPResponse response, bool isGet, IJsonSerializer<T> serializer = null)
{
    try 
    {
        if(serializer == null)
        {
            serializer = new DefaultJsonSerializer<T>();
        }
        j = serializer.Deserialize(response.DataAsText);
    } 
    catch (ArgumentException) 
    {
        /* Conversion problem */
        return;
    }
}

并将其应用于您的Get方法(以便将序列化程序从公共方法传递到私有方法):

public void Get(string Url, CallbackAjaxFinished cbAjaxFinished, IJsonSerializer<T> serializer = null)
{
    // whenever you call ConvertAndCallback
    ConvertAndCallback(param1, param2, serializer); // just pass the same serializer here
}

现在可以将它用于任何类型的实现IJsonSerializer<T>接口的序列化程序,如果没有指定,则使用默认接口。

示例用法:

Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
    baseURL + _urlGetState, /* get Url */
    /* callback Ajax finished: */
    (JsonState j) => { /* do stuff in the callback */ },
    new JsonStateSerializer()
);
// or if you want to use default one
Ajax<JsonState> a = new Ajax<JsonState>();
a.Get(
    baseURL + _urlGetState, /* get Url */
    /* callback Ajax finished: */
    (JsonState j) => { /* do stuff in the callback */ }
);

我不太明白你的意思但会回答我的所作所为。请在评论中澄清这是否是您想要的或者我的答案中有什么不清楚的地方。