如何获得传递给函数的参数名称?

时间:2019-06-10 07:50:05

标签: c# unity3d reflection

很抱歉,如果重复的话,但是我已经做了很多搜索,还没有找到答案

我目前正在使用对象保存/加载系统,该系统允许我在会话之间保存数据,即设置等。我当前的“保护程序”要求我输入一个字符串作为设置的名称,这不太费力。但是,我开始扩展系统,并且我将保存数十个(即使不是数百个)对象(虽然不经常使用)。现在,必须将名称作为参数传递非常困难,因为我正在使用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);
    }

1 个答案:

答案 0 :(得分:0)

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

例如,创建一个名为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();
}

希望这可以解决您的问题。