#c# #unity3d #system.reflection
Вопрос:
Я впервые экспериментирую с отражением в c# (для использования в инструменте разработки, который я создаю), и мне было интересно, может ли кто-нибудь помочь мне получить доступ к тому, к чему я пытаюсь получить доступ?
Приведенный ниже код-это класс, к которому я обращаюсь:
[Serializable]
public class MaterialVariantTarget : BaseNode, IMaterialTarget
{
public MeshRenderer m_Target;
public void ApplyValue(Material value) => m_Target.material = value;
}
Вопрос, на который я хочу ответить, заключается в том, как называется значение, с которым работает функция ApplyValue (). Так что в этом примере это будет MeshRenderer.material
Я разбил проблему на две части. Доступ к типу m_Target (MeshRenderer) и свойству .material.
Во-первых, мне удалось получить доступ:
private Type GetTargetComponentType(Type targetNodeType)
{
foreach (var fieldInfo in targetNodeType.GetFields())
{
if (fieldInfo.Name == "m_Target")
{
var type = fieldInfo.FieldType;
return type;
}
}
return null;
}
Я нахожу доступ к части scond более сложным. Возможно ли вообще то, что я пытаюсь сделать, и если да, то как я могу это сделать?
большое спасибо
[ОБНОВЛЕНИЕ]
Таким образом, кажется, что консенсус состоит в том, что я не могу получить доступ к содержимому метода.
Мне придется просто прибегнуть к написанию необходимой мне информации в виде строки, которую затем можно будет прочитать, но она не идеальна 🙁
Могло бы у меня быть больше возможностей, если бы я организовал его как средство получения/настройки свойств? подобный этому:
[Serializable]
public class MaterialVariantTarget : BaseNode, IMaterialTarget
{
public MeshRenderer m_Target;
private Material m_valueProperty
{
get => m_Target.material;
set => m_Target.material = value;
}
public void ApplyValue(Material value) => m_valueProperty = value;
}
Комментарии:
1. так
m_Target
может быть разного типа в зависимости от класса? Если он всегда имеет типMeshRenderer
, все, что вам нужно сделать, это бросить его2. То, что вам нужно, потребует декомпиляции IL.
3. И
m_Target
то и другое и.material
могло быть по-другому. Так, например, у меня есть еще один, в котором естьTransform
и.localPosition
. Я думаю, я мог бы просто добавить строку const, которая явно перечисляетMeshRenderer.material
, но это делает вещи немного более хрупкими, так как мне нужно будет запомнить, чтобы а) заполнить это и б) обновить его, если что-то изменится в будущем 🙁4. Я не думаю, что ты сможешь
5. Спасибо, я обновил вопрос, возможно, с помощью нового подхода?
Ответ №1:
Вот два удобных расширения, которые я создал для извлечения значения поля или свойства объекта на основе имени или типа:
public static class Extensions
{
public static object GetPropertyOrFieldByName(this object obj, string nameToSearch)
{
foreach (var field in obj.GetType().GetFields())
{
if (field.Name == nameToSearch)
{
return field.GetValue(obj);
}
}
foreach (var property in obj.GetType().GetProperties())
{
if (property.Name == nameToSearch)
{
return property.GetValue(obj);
}
}
return null;
}
public static T GetPropertyOrFieldByType<T>(this object obj) where T : Object
{
foreach (var field in obj.GetType().GetFields())
{
if (field.FieldType == typeof(T))
{
return (T)field.GetValue(obj);
}
}
foreach (var property in obj.GetType().GetProperties())
{
if (property.PropertyType == typeof(T))
{
return (T)property.GetValue(obj);
}
}
return null;
}
}
Использование, которое вам требуется, может быть реализовано таким образом:
object target = yourMaterialVariantTarget.GetPropertyOrFieldByName("m_Target");
Material material = target.GetPropertyOrFieldByType<Material>();
material.color = Color.red;
Комментарии:
1. эй, извини, что не вернулся к этому 🙂
2. Хотя это хорошее решение для доступа к значению поля, к сожалению, это не совсем те данные, к которым я пытался получить доступ. В этом решении мне нужно было бы заранее знать, что свойство, которое я искал, относится к типу материала .
3. То, на чем я застрял, — это попытка определить имя этого поля (не зная его типа заранее) на основе отражаемого класса. Таким образом, в одном случае это может быть свойство типа Material , называемое material , в компоненте MeshRenderer, а в другом-свойство типа Vector3 , называемое localPosition , из компонента преобразования . Также возможно, что мы могли бы быть свойством localScale, к которому я пытаюсь получить доступ в том же компоненте преобразования , который также будет иметь тип Vector3 , поэтому, к сожалению, знание типа не решает проблему.
4. Последнее, что следует отметить, — это то, что на самом деле мне не нужна стоимость недвижимости. Я ищу название объекта недвижимости. таким образом, моим идеальным возвратом был бы материал / локальное расположение / локальный масштаб в виде строки.
5. @RobertJHomewood честно говоря, вам следует переписать вопрос, объяснив, чего вы намерены достичь и почему, и предоставить несколько примеров примеров. В нынешнем виде это немного сбивает с толку.