如何检查参数类型? [英] How to check for parameter type?
问题描述
我已经将自己的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 ConvertAndCallback
you 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 Attribute
s 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屋!