【问题标题】:How do I get the name of a parameter passed to my function?如何获取传递给我的函数的参数名称?
【发布时间】:2019-06-10 07:50:05
【问题描述】:

(对不起,如果这是重复的,但我已经做了很多搜索,但没有找到答案)

我目前正在开发一个对象保存/加载系统,该系统允许我在会话之间保存数据,即设置等。我当前的“保护程序”要求我输入一个字符串作为设置的名称,这不是太多的工作。然而,我开始扩展系统,我将保存数十个甚至数百个对象(虽然不经常)。现在,必须将名称作为参数传递现在非常很棘手,因为我正在使用for 循环,所以除非我想为名称创建一个新列表,否则我需要一个更好的方法.

编辑(添加我想要的示例):

    void LogName(object obj)
{

    Debug.Log(GetNameOfParam(obj));
    DoStuff();
}
LogName(ObjectToSave);

这应该记录“ObjectToSave”而不是“obj”

我尝试了许多不同的解决方案:
obj.GetType().Name,它只输出类型名称
nameof(obj),它输出“obj” 甚至

public static string GetName<T>(Expression<Func<T>> expr)
    {
        MemberExpression body = ((MemberExpression)expr.Body);
        string name = body.Member.Name;
        //object value = ((FieldInfo)body.Member).GetValue(((ConstantExpression)body.Expression).Value);
        return name;
    }
    GetName(() => obj)

这也给了我“obj”。

编辑(添加代码): 覆盖代码:

private void OverwriteObject(object obj)
{
    string name = obj.GetType().Name;
    Debug.Log($"GetType.Name:{obj.GetType().Name}");
    Debug.Log($"nameof:{nameof(obj)}");
    Debug.Log($"GetName<T>:{ObjectExtensions.GetName(() => obj)}");

    string path = Paths.SettingsSaveLocation + Paths.SettingFilePrefix + name + Paths.SettingFileSuffix;
    //If setting file exist, read it
    if (File.Exists(path))
    {
        try
        {
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                //Create buffer and read data
                byte[] data = new byte[fs.Length];
                fs.Read(data, 0, (int)fs.Length);
                //Load data into setting object
                JsonUtility.FromJsonOverwrite(Encoding.UTF8.GetString(data), obj);
            }
        }
        catch (Exception e)
        {
            Debug.LogException(e);
        }
    }
    //Otherwise, create a new one
    else
    {
        WriteObj(name, obj);
    }
}

编写代码:

    private void WriteObject(string name, object obj)
{
    string path = Paths.SettingsSaveLocation + Paths.SettingFilePrefix + name + Paths.SettingFileSuffix;
    using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
    {
        //Use prettyPrint so it looks nicer
        string data = JsonUtility.ToJson(obj, true);
        fs.Write(Encoding.UTF8.GetBytes(data), 0, data.Length);/**/
    }
}

For 循环(不完整,需要工作):

foreach (var obj in GameObject.FindGameObjectsWithTag("Enemy"))
    {
        WriteObject("Object name is xyzasd123", obj);
    }

【问题讨论】:

  • "nameof(obj),输出obj" - 那么你期望它输出什么?如果您的参数名称是obj,那不是您要问的吗?
  • 我很困惑......如果不是“obj”,你想得到什么答案?
  • 第一条评论中的链接有什么问题?这显示了如何完全按照您的要求进行操作。
  • @RowanRadosav-McRae 如果不先设置自定义合同解析器和转换器,您将无法使用 Json Dot Net 序列化单一行为类。

标签: c# unity3d reflection


【解决方案1】:

如果它不是您要查找的类型名称并且不是您的方法的反射参数名称,那么您需要将该名称存储在每个对象的公共属性中。

例如创建一个名为IObjectName的接口。

public interface IObjectname
{
    string ObjectName { get; set; }
}

每个应该有名字的对象都应该实现这个接口。

现在你可以把你的方法改成这样:

void LogName(IObjectName obj)
{
    Debug.Log(obj.Name);
    DoStuff();
}

或者你可以转换参数IObjectName,但是如果类型没有实现接口,这将抛出一个InvalidCastException

例如:

void LogName(object obj)
{
    // Risk that InvalidCastException will be thrown.
    Debug.Log((obj as IObjectName).Name);
    DoStuff();
}

希望这能解决您的问题。

【讨论】:

  • 不完全是我想要的,但足够接近,而且是一个不错的答案。
猜你喜欢
  • 2019-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
相关资源
最近更新 更多