'system.object []' 'to'myObject [] '의 객체를 캐스트 할 수 없으면 무엇을 제공합니까?
-
03-07-2019 - |
문제
대본:
나는 현재 3 개의 유사한 웹 서비스를 하나의 유용한 클래스로 추상화하기 위해 레이어를 작성하고 있습니다. 각 웹 서비스는 공통성을 공유하는 일련의 객체를 노출시킵니다. 나는 공통성을 악용하는 일련의 중개 객체를 만들었습니다. 그러나 내 레이어에서는 웹 서비스 객체와 객체를 변환해야합니다.
반사를 사용하여 웹 서비스를 호출하기 전에 실행 시간에 적절한 유형을 만들었습니다.
public static object[] CreateProperties(Type type, IProperty[] properties)
{
//Empty so return null
if (properties==null || properties.Length == 0)
return null;
//Check the type is allowed
CheckPropertyTypes("CreateProperties(Type,IProperty[])",type);
//Convert the array of intermediary IProperty objects into
// the passed service type e.g. Service1.Property
object[] result = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
IProperty fromProp = properties[i];
object toProp = ReflectionUtility.CreateInstance(type, null);
ServiceUtils.CopyProperties(fromProp, toProp);
result[i] = toProp;
}
return result;
}
내 서비스 구현 중 하나에서 내 호출 코드는 다음과 같습니다.
Property[] props = (Property[])ObjectFactory.CreateProperties(typeof(Property), properties);
_service.SetProperties(folderItem.Path, props);
따라서 각 서비스는 iproperty 인터페이스의 자신의 구현 뒤에 숨어있는 다른 "속성"객체를 노출시킵니다.
반사 코드는 요소가 적절한 유형 인 객체 배열을 생성하는 단위 테스트에서 작동합니다. 그러나 호출 코드는 실패합니다.
System.InvalidCastException : 'system.object []'유형의 개체를 캐스트 할 수 없음 'myProject.property [
어떤 아이디어?
포함 된 객체가 변환 가능하는 한 객체의 캐스트가 작동한다는 인상을 받았습니까?
해결책
대안 답변 : 제네릭.
public static T[] CreateProperties<T>(IProperty[] properties)
where T : class, new()
{
//Empty so return null
if (properties==null || properties.Length == 0)
return null;
//Check the type is allowed
CheckPropertyTypes("CreateProperties(Type,IProperty[])",typeof(T));
//Convert the array of intermediary IProperty objects into
// the passed service type e.g. Service1.Property
T[] result = new T[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
T[i] = new T();
ServiceUtils.CopyProperties(properties[i], t[i]);
}
return result;
}
그런 다음 호출 코드가됩니다.
Property[] props = ObjectFactory.CreateProperties<Property>(properties);
_service.SetProperties(folderItem.Path, props);
훨씬 더 깨끗합니다 :)
다른 팁
기본적으로, 아니요. 배열 공분산의 몇 가지 제한된 용도가 있지만 원하는 배열 유형을 간단히 아는 것이 좋습니다. 일반적인 배열이 있습니다. ConvertAll은 충분히 쉽습니다 (적어도 C# 3.0에서는 더 쉽습니다) :
Property[] props = Array.ConvertAll(source, prop => (Property)prop);
C# 2.0 버전 (의미가 동일)은 안구 친화적이지 않습니다.
Property[] props = Array.ConvertAll<object,Property>(
source, delegate(object prop) { return (Property)prop; });
또는 올바른 크기의 새 속성을 만들고 수동으로 (또는 Array.Copy
).
당신의 것들의 예로서 ~할 수 있다 배열 공분산으로 :
Property[] props = new Property[2];
props[0] = new Property();
props[1] = new Property();
object[] asObj = (object[])props;
여기서 "Asobj"는입니다 아직 ㅏ Property[]
- 단순히 액세스 할 수 있습니다 object[]
. C# 2.0 이상에서 제네릭은 일반적으로 배열 공분산보다 더 나은 옵션을 만듭니다.
다른 사람들이 말했듯이, 배열은 시작하기에 적합한 유형이어야합니다. 다른 답변은 사실 후 [] 진정한 객체를 변환하는 방법을 보여 주었지만 사용하기 시작하기에 올바른 종류의 배열을 만들 수 있습니다. Array.createInstance:
object[] result = (object[]) Array.CreateInstance(type, properties.Length);
가정합니다 type
참조 유형이므로 작동해야합니다. 배열은 올바른 유형이지만이를 object[]
그냥 채우기 위해.
배열을 변환 할 수 없습니다. 객체와 다른 객체 배열을 반환합니다. 노력하다 Array.convertAll
맞지 만, 그렇다고해서 다른 유형의 컨테이너에 타입 객체의 컨테이너를 캐스트 할 수는 없습니다. 객체 []는 객체와 같은 것이 아닙니다 (이상하게도 객체 []를 대상에 캐스트 할 수 있음).
C# 2.0에서 ~할 수 있다 제네릭을 사용하지 않고 컴파일 시간에 원하는 유형을 모르고 반사를 사용하여이를 수행하십시오.
//get the data from the object factory
object[] newDataArray = AppObjectFactory.BuildInstances(Type.GetType("OutputData"));
if (newDataArray != null)
{
SomeComplexObject result = new SomeComplexObject();
//find the source
Type resultTypeRef = result.GetType();
//get a reference to the property
PropertyInfo pi = resultTypeRef.GetProperty("TargetPropertyName");
if (pi != null)
{
//create an array of the correct type with the correct number of items
pi.SetValue(result, Array.CreateInstance(Type.GetType("OutputData"), newDataArray.Length), null);
//copy the data and leverage Array.Copy's built in type casting
Array.Copy(newDataArray, pi.GetValue(result, null) as Array, newDataArray.Length);
}
}
모든 type.getType ( "outputData") 호출 및 getProperty ( "PropertyName")를 구성 파일에서 읽는 일부 코드로 바꾸려고합니다.
나는 또한 일반적인 것을 사용하여 SomecomplexObject의 생성을 지시합니다.
T result = new T();
Type resultTypeRef = result.GetType();
그러나 나는 당신이 제네릭을 사용할 필요가 없다고 말했습니다.
성능/효율성에 대한 보장은 없지만 작동합니다.