Преобразование из объекта в QueryString [дубликат]

Буквально самый простой способ исправить NullReferenceExeption имеет два пути. Если у вас есть GameObject, например, с прикрепленным скриптом и переменной с именем rb (rigidbody), эта переменная начнет пустую, когда вы начнете игру. Вот почему вы получаете NullReferenceExeption, потому что на компьютере нет данных, хранящихся в этой переменной.

В качестве примера я буду использовать переменную RigidBody. Мы можем добавить данные действительно легко на самом деле несколькими способами:

  1. Добавить RigidBody к вашему объекту с помощью AddComponent> Физика> Rigidbody Затем зайдите в свой скрипт и введите rb = GetComponent<Rigidbody>();. Эта строка кода работает лучше всего под ваши функции Start() или Awake().
  2. Вы можете добавить компонент программно и назначить переменную одновременно с одной строкой кода: rb = AddComponent<RigidBody>();

Дальнейшие заметки: если вы хотите, чтобы единство добавлялось компонент для вашего объекта, и вы, возможно, забыли добавить его, вы можете ввести [RequireComponent(typeof(RigidBody))] над объявлением класса (пробел ниже всех ваших приложений). Наслаждайтесь и получайте удовольствие от игр!

44
задан Benjamin 27 July 2011 в 18:00
поделиться

10 ответов

Я на 99% уверен, что для этого нет встроенного метода утилиты. Это не очень обычная задача, так как веб-сервер обычно не отвечает с помощью строки ключа / значения URLEncoded.

Как вы относитесь к смешению отражения и LINQ? Это работает:

var foo = new EditListItemActionModel() {
  Id = 1,
  State = 26,
  Prefix = "f",
  Index = "oo",
  ParentID = null
};

var properties = from p in foo.GetType().GetProperties()
                 where p.GetValue(foo, null) != null
                 select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(foo, null).ToString());

// queryString will be set to "Id=1&State=26&Prefix=f&Index=oo"                  
string queryString = String.Join("&", properties.ToArray());

Обновление:

Чтобы написать метод, возвращающий представление QueryString любого объекта с 1 глубиной, вы можете сделать это:

public string GetQueryString(object obj) {
  var properties = from p in obj.GetType().GetProperties()
                   where p.GetValue(obj, null) != null
                   select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString());

  return String.Join("&", properties.ToArray());
}

// Usage:
string queryString = GetQueryString(foo);

Вы также можете сделать это методом расширения без дополнительной работы

public static class ExtensionMethods {
  public static string GetQueryString(this object obj) {
    var properties = from p in obj.GetType().GetProperties()
                     where p.GetValue(obj, null) != null
                     select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString());

    return String.Join("&", properties.ToArray());
  }
}

// Usage:
string queryString = foo.GetQueryString();
77
ответ дан Dave Ward 1 September 2018 в 02:06
поделиться

Эти методы не работают с этим королем свойств:

public List<int?> list
0
ответ дан Alex 1 September 2018 в 02:06
поделиться
public static class UrlHelper
{
    public static string ToUrl(this Object instance)
    {
        var urlBuilder = new StringBuilder();
        var properties = instance.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
        for (int i = 0; i < properties.Length; i++)
        {
            urlBuilder.AppendFormat("{0}={1}&", properties[i].Name, properties[i].GetValue(instance, null));
        }
        if (urlBuilder.Length > 1)
        {
            urlBuilder.Remove(urlBuilder.Length - 1, 1);
        }
        return urlBuilder.ToString();
    }
}
1
ответ дан Alexander 1 September 2018 в 02:06
поделиться

На основе популярных ответов мне нужно было обновить код для поддержки массивов. Совместное использование реализации:

public string GetQueryString(object obj)
{
    var result = new List<string>();
    var props = obj.GetType().GetProperties().Where(p => p.GetValue(obj, null) != null);
    foreach (var p in props)
    {
        var value = p.GetValue(obj, null);
        var enumerable = value as ICollection;
        if (enumerable != null)
        {
            result.AddRange(from object v in enumerable select string.Format("{0}={1}", p.Name, HttpUtility.UrlEncode(v.ToString())));
        }
        else
        {
            result.Add(string.Format("{0}={1}", p.Name, HttpUtility.UrlEncode(value.ToString())));
        }
    }

    return string.Join("&", result.ToArray());
}
5
ответ дан Alvis 1 September 2018 в 02:06
поделиться

Это мое решение:

public static class ObjectExtensions
{
    public static string ToQueryString(this object obj)
    {
        if (!obj.GetType().IsComplex())
        {
            return obj.ToString();
        }

        var values = obj
            .GetType()
            .GetProperties()
            .Where(o => o.GetValue(obj, null) != null);

        var result = new QueryString();

        foreach (var value in values)
        {
            if (!typeof(string).IsAssignableFrom(value.PropertyType) 
                && typeof(IEnumerable).IsAssignableFrom(value.PropertyType))
            {
                var items = value.GetValue(obj) as IList;
                if (items.Count > 0)
                {
                    for (int i = 0; i < items.Count; i++)
                    {
                        result = result.Add(value.Name, ToQueryString(items[i]));
                    }
                }
            }
            else if (value.PropertyType.IsComplex())
            {
                result = result.Add(value.Name, ToQueryString(value));
            }
            else
            {
                result = result.Add(value.Name, value.GetValue(obj).ToString());
            }
        }

        return result.Value;
    }

    private static bool IsComplex(this Type type)
    {
        var typeInfo = type.GetTypeInfo();
        if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            // nullable type, check if the nested type is simple.
            return IsComplex(typeInfo.GetGenericArguments()[0]);
        }
        return !(typeInfo.IsPrimitive
          || typeInfo.IsEnum
          || type.Equals(typeof(Guid))
          || type.Equals(typeof(string))
          || type.Equals(typeof(decimal)));
    }
}

Я использую это расширение для моего теста интеграции, он отлично работает:)

0
ответ дан Cedric Arnould 1 September 2018 в 02:06
поделиться

Я искал решение для Windows 10 (UWP). Взяв подход Relection, предложенный Dave , а после добавления пакета Microsoft.AspNet.WebApi.Client Nuget, я использовал следующий код, который обрабатывает Url-кодирование значений свойств:

 private void AddContentAsQueryString(ref Uri uri, object content)
    {            
        if ((uri != null) && (content != null))
        {
            UriBuilder builder = new UriBuilder(uri);

            HttpValueCollection query = uri.ParseQueryString();

            IEnumerable<PropertyInfo> propInfos = content.GetType().GetRuntimeProperties();

            foreach (var propInfo in propInfos)
            {
                object value = propInfo.GetValue(content, null);
                query.Add(propInfo.Name, String.Format("{0}", value));
            }

            builder.Query = query.ToString();
            uri = builder.Uri;                
        }
    }
0
ответ дан Community 1 September 2018 в 02:06
поделиться

Столкнувшись с подобной ситуацией, я сделал, чтобы XML сериализовал объект и передал его как параметр строки запроса. Трудность с этим подходом заключалась в том, что, несмотря на кодирование, принимающая форма генерирует исключение, говорящее «потенциально опасный запрос ...». Способ, которым я обходился, состоял в том, чтобы зашифровать сериализованный объект и затем закодировать его, чтобы передать его как параметр строки запроса. Это, в свою очередь, сделало доказательство подделки строки запроса (бонус, блуждающий по территории HMAC)!

FormA XML сериализует объект> шифрует сериализованную строку> encode> pass в качестве строки запроса в FormB FormB расшифровывает значение параметра запроса (так же декодирует request.querystring)> десериализует полученную строку XML в объект с помощью XmlSerializer.

Я могу поделиться своим кодом VB.NET по запросу с тем, какIdidit-at-applecart-dot-net

0
ответ дан Denny Jacob 1 September 2018 в 02:06
поделиться

Основываясь на хороших идеях из других комментариев, я сделал общий метод расширения .ToQueryString (), который можно использовать для любого объекта.

public static class UrlHelpers
{
    public static string ToQueryString(this object request, string separator = ",")
    {
        if (request == null)
            throw new ArgumentNullException("request");

        // Get all properties on the object
        var properties = request.GetType().GetProperties()
            .Where(x => x.CanRead)
            .Where(x => x.GetValue(request, null) != null)
            .ToDictionary(x => x.Name, x => x.GetValue(request, null));

        // Get names for all IEnumerable properties (excl. string)
        var propertyNames = properties
            .Where(x => !(x.Value is string) && x.Value is IEnumerable)
            .Select(x => x.Key)
            .ToList();

        // Concat all IEnumerable properties into a comma separated string
        foreach (var key in propertyNames)
        {
            var valueType = properties[key].GetType();
            var valueElemType = valueType.IsGenericType
                                    ? valueType.GetGenericArguments()[0]
                                    : valueType.GetElementType();
            if (valueElemType.IsPrimitive || valueElemType == typeof (string))
            {
                var enumerable = properties[key] as IEnumerable;
                properties[key] = string.Join(separator, enumerable.Cast<object>());
            }
        }

        // Concat all key/value pairs into a string separated by ampersand
        return string.Join("&", properties
            .Select(x => string.Concat(
                Uri.EscapeDataString(x.Key), "=",
                Uri.EscapeDataString(x.Value.ToString()))));
    }
}

Он также будет работать для объектов, обладающих свойствами типа Array и общих списков, если они содержат только примитивы или строки.

Попробуйте, комментарии приветствуются: Сериализовать объект в строку запроса с помощью Reflection

10
ответ дан johnnyRose 1 September 2018 в 02:06
поделиться

Еще один вариант вышеизложенного, но я хотел использовать существующие атрибуты DataMember в моем классе модели, поэтому только те свойства, которые я хочу сериализовать, отправляются на сервер в URL-адресе в запросе GET.

    public string ToQueryString(object obj)
    {
        if (obj == null) return "";

        return "?" + string.Join("&", obj.GetType()
                                   .GetProperties()
                                   .Where(p => Attribute.IsDefined(p, typeof(DataMemberAttribute)) && p.GetValue(obj, null) != null)
                                   .Select(p => $"{p.Name}={Uri.EscapeDataString(p.GetValue(obj).ToString())}"));
    }
0
ответ дан Peter Kerr 1 September 2018 в 02:06
поделиться

Вот что я написал, что делает то, что вам нужно.

    public string CreateAsQueryString(PageVariables pv) //Pass in your EditListItemActionModel instead
    {
        int i = 0;
        StringBuilder sb = new StringBuilder();

        foreach (var prop in typeof(PageVariables).GetProperties())
        {
            if (i != 0)
            {
                sb.Append("&");
            }

            var x = prop.GetValue(pv, null).ToString();

            if (x != null)
            {
                sb.Append(prop.Name);
                sb.Append("=");
                sb.Append(x.ToString());
            }

            i++;
        }

        Formating encoding = new Formating();
        // I am encoding my query string - but you don''t have to
        return "?" + HttpUtility.UrlEncode(encoding.RC2Encrypt(sb.ToString()));  
    }
0
ответ дан TheGeekYouNeed 1 September 2018 в 02:06
поделиться