문자열 값으로 반사하여 속성을 설정합니다
-
23-08-2019 - |
문제
반사를 통해 객체의 속성을 유형 값으로 설정하고 싶습니다. string
. 예를 들어, 내가 a가 있다고 가정 해 봅시다 Ship
재산이있는 클래스 Latitude
,, 그것은 a double
.
내가하고 싶은 일은 다음과 같습니다.
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, value, null);
그대로, 이것은 던졌습니다 ArgumentException
:
'System.String'유형의 객체는 'System.Double'유형으로 변환 할 수 없습니다.
값을 기준으로 적절한 유형으로 어떻게 변환 할 수 있습니까? propertyInfo
?
해결책
당신이 사용할 수있는 Convert.ChangeType()
- 런타임 정보를 사용할 수 있습니다. IConvertible
표현 형식을 변경하려면 유형입니다. 그러나 모든 전환이 가능하지는 않지만 그렇지 않은 유형의 변환을 지원하려면 특별한 사례 논리를 작성해야 할 수도 있습니다. IConvertible
.
해당 코드 (예외 처리 또는 특수 사례 로직)는 다음과 같습니다.
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
다른 팁
다른 여러 사람들이 말했듯이, 당신은 Convert.ChangeType
:
propertyInfo.SetValue(ship,
Convert.ChangeType(value, propertyInfo.PropertyType),
null);
사실, 나는 당신이 전체를 보는 것이 좋습니다 Convert
수업.
이 수업과 다른 많은 유용한 수업은 System
네임 스페이스. 나는 매년 그 네임 스페이스를 스캔하여 내가 놓친 기능을 확인하는 것이 유용하다고 생각합니다. 시도 해봐!
많은 사람들이 추천하는 것을 알았습니다 Convert.ChangeType
- 이것은 어떤 경우에도 효과가 있지만 참여를 시작하자마자 nullable
받기 시작할 유형 InvalidCastExceptions
:
래퍼는 몇 년 전에 이것을 처리하기 위해 작성되었지만 완벽하지는 않습니다.
유형 변환기를 사용할 수 있습니다 (오류 확인 없음) :
Ship ship = new Ship();
string value = "5.5";
var property = ship.GetType().GetProperty("Latitude");
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);
코드 구성 측면에서 종류의 믹스 인 이는 다음과 같은 코드를 초래할 것입니다.
Ship ship = new Ship();
ship.SetPropertyAsString("Latitude", "5.5");
이것은이 코드로 달성 될 것입니다.
public interface MPropertyAsStringSettable { }
public static class PropertyAsStringSettable {
public static void SetPropertyAsString(
this MPropertyAsStringSettable self, string propertyName, string value) {
var property = TypeDescriptor.GetProperties(self)[propertyName];
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);
}
}
public class Ship : MPropertyAsStringSettable {
public double Latitude { get; set; }
// ...
}
MPropertyAsStringSettable
다양한 클래스에 대해 재사용 할 수 있습니다.
자신만의 관습을 만들 수도 있습니다 변환기 유형 속성 또는 클래스에 첨부하려면 :
public class Ship : MPropertyAsStringSettable {
public Latitude Latitude { get; set; }
// ...
}
[TypeConverter(typeof(LatitudeConverter))]
public class Latitude { ... }
나는 답을 시도했다 lbushkin 그리고 그것은 훌륭하게 작동했지만 널 값과 무효 필드에는 효과가 없습니다. 그래서 나는 이것을 이것으로 변경했습니다.
propertyName= "Latitude";
PropertyInfo propertyInfo = ship.GetType().GetProperty(propertyName);
if (propertyInfo != null)
{
Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
object safeValue = (value == null) ? null : Convert.ChangeType(value, t);
propertyInfo.SetValue(ship, safeValue, null);
}
당신은 아마도 Convert.ChangeType
방법. 예를 들어:
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
사용 Convert.ChangeType
그리고 유형이 PropertyInfo.PropertyType
.
propertyInfo.SetValue( ship,
Convert.ChangeType( value, propertyInfo.PropertyType ),
null );
나는 일반적인 대답으로 이것에 대답 할 것이다. 일반적으로 이러한 답변은 Guid와 함께 작동하지 않습니다. 다음은 Guids가있는 작업 버전입니다.
var stringVal="6e3ba183-89d9-e611-80c2-00155dcfb231"; // guid value as string to set
var prop = obj.GetType().GetProperty("FooGuidProperty"); // property to be setted
var propType = prop.PropertyType;
// var will be type of guid here
var valWithRealType = TypeDescriptor.GetConverter(propType).ConvertFrom(stringVal);
또는 시도 할 수 있습니다.
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType), null);
//But this will cause problems if your string value IsNullOrEmplty...
Metro 앱을 작성하는 경우 다른 코드를 사용해야합니다.
Ship ship = new Ship();
string value = "5.5";
PropertyInfo propertyInfo = ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
propertyInfo.SetValue(ship, Convert.ChangeType(value, propertyInfo.PropertyType));
메모:
ship.GetType().GetTypeInfo().GetDeclaredProperty("Latitude");
대신에
ship.GetType().GetProperty("Latitude");
다음 코드를 사용하면 문제를 해결해야합니다.
item.SetProperty(prop.Name, Convert.ChangeType(item.GetProperty(prop.Name).ToString().Trim(), prop.PropertyType));
반사로 놀고 싶습니까, 아니면 프로덕션 소프트웨어를 구축하려고합니까? 반사를 사용하여 속성을 설정하는 이유에 의문을 제기합니다.
Double new_latitude;
Double.TryParse (value, out new_latitude);
ship.Latitude = new_latitude;