'system.object []' 'to'myObject [] '의 객체를 캐스트 할 수 없으면 무엇을 제공합니까?

StackOverflow https://stackoverflow.com/questions/212429

문제

대본:

나는 현재 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();

그러나 나는 당신이 제네릭을 사용할 필요가 없다고 말했습니다.

성능/효율성에 대한 보장은 없지만 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top