如何检查参数类型? [英] How to check for parameter type?

查看:69
本文介绍了如何检查参数类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经将自己的Ajax设为泛型"(不能忘记您在C#中如何称呼此原理),如下所示(仅相关函数):

I've made my own Ajax "generic" (cant remember how you call this principle in C#) like this (only relevant functions):

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无法处理嵌套数组(...).

The problem is that Unity's JsonUtility doesnt handle nested arrays (...).

长话短说,我想在我的通用"内容中传递自定义的"json解码"函数回调(默认值= null),并在ConvertThenCallback()函数中执行以下操作:

To make a long story short, I'd like in my "generic" stuff, to pass a custom "json decode" function callback, default=null, and in the ConvertThenCallback() function, do this:

  • 如果没有自定义函数,请调用j = (T)JsonUtility.FromJson<T>(response.DataAsText);(就像现在已经一样)
  • 如果有自定义函数,请调用j = (T)callback(response.DataAsText);
  • if there's no custom function, call j = (T)JsonUtility.FromJson<T>(response.DataAsText); (like it already is now)
  • if there's a custom function, call something like j = (T)callback(response.DataAsText);

您将如何在C#中做到这一点?

How would you do that in C#?

更新

这是我的JsonState +依赖项声明:

Here's my JsonState + dependencies declaration:

[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实用程序无法解码嵌套数组,因此当我调用JsonUtility.FromJson()时,属性JsonGameDataCell[][] board始终设置为null.因此,我必须实现自己的Json解码器.我将使用效果很好的SimpleJSON,但我只想仅在特定情况下使用此解码器 .

And my actual problem is that Unity Json utility can't decode nested arrays, so the property JsonGameDataCell[][] board is always set to null when I call JsonUtility.FromJson(). So I have to implement my own Json decoder. I'll use SimpleJSON which works very well, but I just want to use thise decoder only in that specific case.

推荐答案

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

Seems to me that you're seeking something called an interface. You can use them to mark some objects so that the application "knows" how to treat them.

您可以这样创建interface:

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

现在在您的ConvertAndCallback中,您只需检查if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))

Now in your ConvertAndCallbackyou can just check if(typeof(T).GetInterfaces().Any(i => i == typeof(ICustomJson)))

如果这样做,您可以创建强制转换为ICustomJson的该类的实例并调用FromJson(string)方法.

If it does you can just create an instance of that class casted to ICustomJson and call FromJson(string) method.

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

Remember that your object can have no default ( parameterless ) constructor so you can create an uninitialized version of that class.

示例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,但仅用于反序列化器部分.这将涉及另一个类(或工厂)来产生用于指定类型的解串器.


Another solution would be ( again ) to use an interface but only for deserializer part. This will involve another class ( or a factory ) to produce a deserializer for the specified type.

您可以在T Deserialize(string)string Serialize(T)中使用两个方法创建一个名为IJsonSerializer的接口:

You can create an interface called IJsonSerializer with two methods inside T Deserialize(string) and string Serialize(T):

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

现在有了此接口,创建一个将实现此接口的类

Now having this interface, create a class which will implement this

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方法中使用哪个.

Having these two would be easier to distinguish which one to use later in your ConvertAndCallback method.

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

Now if you want you can create some Attributes to mark which serializer will be applied to which object or use some factory for that.

我将采用最简单的方法,只是修改ConvertAndCallback方法,使其具有另一个(可选)参数.

I will go with the easiest method and just modify ConvertAndCallback method so that it will have another ( optional ) parameter.

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方法(以便将序列化程序从公共方法传递到私有方法):

And apply this to your Get method too ( so that the serializer would be passed from public to private methods ):

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>接口的任何类型的序列化程序一起使用,或者如果未指定,则与默认序列化程序一起使用.

You can now use it with any kind of serializer that implements IJsonSerializer<T> interface or with the default one if none specified.

示例用法:

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 */ }
);


我不太了解您的意思,但是会回答我所做的部分.请在评论中阐明您是否要这样做,或者我的答案中有不清楚的地方.


I don't quite understand what you meant but will answer the part I do. Please clarify in the comment if that's what you wanted or if there's something unclear in my answer.

这篇关于如何检查参数类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆