2009-11-23 5 views
5

전 검색했지만 내 질문에 대한 정확한 답을 찾을 수 없습니다. 예를 들어 다음 코드를 예로 들어 보겠습니다.반사를 사용하여 중첩 된 속성 값 설정

이제 사용자가 회사의 고객에 대한 정보를 입력 할 수있는 텍스트 입력란이 많은 양식을 설정했습니다. 이러한 필드 중 하나는 Tag 속성이 EmailAddress로 설정된 전자 메일 주소 텍스트 필드입니다. TextBox의 Tag를보고 전체 Company 객체를 반복하여 일치하는 Name이있는 속성을 찾고 해당 값을 TextBox의 Text 속성으로 설정하려고합니다. 속성을 찾을 수는 있지만 값을 설정하는 것은 상당히 어려워졌습니다. 여기에 내가 지금까지이 작업은 다음과 같습니다

foreach (PropertyInfo info in m_objCompany.GetType().GetProperties()) 
{ 
    if (info.PropertyType != typeof(System.String)) 
    { 
     foreach (PropertyInfo info2 in info.PropertyType.GetProperties()) 
     { 
      if (objTextBox.Tag.Equals(info2.Name)) 
      { 
       if (info2.CanWrite) 
       { 
        Object objValue = Convert.ChangeType(objTextBox.Text, info.PropertyType); 
        info2.SetValue(m_objCompany, objValue, null); 
       } 
      } 

     } 
    } 
} 

내 문제는 내가 코드를 실행할 때 내가의 ChangeType 및/또는 SetValue를에서 오류가 발생한다는 것입니다. 문제는 Reflection이 info2에서 멈추고 Type of Details로 값을 설정하려고 시도한다는 것입니다. 이는 Property EmailAddress의 부모이기 때문입니다.

SetValue를 적절한 속성으로 가리키는 방법을 결정하는 데 도움이 될 것입니다. 여러분이 내 수업을 거의 추측 할 수 있다고 확신 하듯이 거의 100 개의 속성으로 제공된 예제보다 큰 거래가 있습니다. 대부분은 모두 TextBox 객체를 통해 수동으로 입력되는 문자열 값입니다. 나는 모든 TextBox 객체에 의해 호출 될 수있는 하나의 루틴을 만들려고 시도한다. 객체의 Tag 속성을 사용하여 설정하려고하는 클래스의 Property를 나타낼 수있다. 거기서부터 XML 직렬화 토지가 떨어져 있습니다.

info2.SetValue(m_objCompany, objValue, null); 

답변

7

내면의 라인은 외부 개체의 내부 특성 (정보 2)의 값을 설정하기 위해 노력하고있다. 외부 오브젝트에는 내부 오브젝트가 없습니다. 다음 설정하려는 속성 건너 때

public void Bar(object m_objCompany) 
    { 
     foreach (PropertyInfo info in m_objCompany.GetType().GetProperties()) 
     { 
      if (info.PropertyType != typeof(System.String)) 
      { 
       // Somehow create the outer property 
       object outerPropertyValue = info.PropertyType.GetConstructor(new Type[] { }).Invoke(new object[] { }); 

       foreach (PropertyInfo info2 in info.PropertyType.GetProperties()) 
       { 
        if ("blah" == "blah") 
        { 
         if (info2.CanWrite) 
         { 
          Object innerPropertyValue = Convert.ChangeType("blah", info2.PropertyType); 
          info2.SetValue(outerPropertyValue, innerPropertyValue, null); 
         } 
        } 

       } 

       info.SetValue(m_objCompany, outerPropertyValue, null); 
      } 
     } 
    } 

, 당신은 (outerPropertyValue)을 그 속성을 만들 필요가 설정 해당 속성의 속성 : 당신은 아마 원하는 것은

,이 같은 것입니다 (innerPropertyValue를 통해), 원래 객체 (m_objCompany)에 outer 속성을 설정합니다.

+0

놀라운. 이러한 속도와 정확성! 엄청 고마워!! 그것은 매력처럼 작용했습니다. – Jeff

+0

기꺼이 도와 드리겠습니다. – McKay

5

다음은 Reflection에 사용하는 코드입니다. 이 경우 SetValue 메쏘드로 전화하기를 원할 것입니다.

Reflector.SetValue(TARGET_OBJECT, "Customer.Details.PhoneNumber", "ValueToSet"); 

UPDATE : 추가 누락 된 ConversionResult 구조체. 누락해서 죄송합니다.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics.CodeAnalysis; 
using System.Globalization; 
using System.Reflection; 

namespace YourNamespace 
{ 
    public struct ConversionResult 
    { 
    public Boolean Success; 
    public object ConvertedValue; 
    } 

    public static class Reflector 
    { 
    private static BindingFlags DefaultBindings = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic; 
    #region Public Methods 
    /// <summary> 
    /// Execute the "codeToExecute" string on the "source" object 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="codeToExecute">Code that should be executed ex. 'Person.Age'</param> 
    /// <returns>The result of execute codeToExecute on source</returns> 
    public static object GetValue(object source, String codeToExecute) 
    { 
     ReflectorResult reflectorResult = GetReflectorResult(source, codeToExecute, true, false); 
     if (reflectorResult != null) 
     { 
     return reflectorResult.Value; 
     } 
     return null; 
    } 

    /// <summary> 
    /// Sets the "source" object to the "value" specified in "codeToExecute" 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="codeToExecute">Code that should be executed ex. 'Person.Age'</param> 
    /// <param name="value">Value to set the source+codeToExecute to.</param> 
    public static Boolean SetValue(object source, String codeToExecute, object value) 
    { 
     return SetValue(source, codeToExecute, value, false); 
    } 

    /// <summary> 
    /// Sets the "source" object to the "value" specified in "codeToExecute" 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="codeToExecute">Code that should be executed ex. 'Person.Age'</param> 
    /// <param name="value">Value to set the source+codeToExecute to.</param> 
    /// <param name="createIfNotExists">Creates items it cannot find</param> 
    public static Boolean SetValue(object source, String codeToExecute, object value, Boolean createIfNotExists) 
    { 
     Boolean executed = true; 

     ReflectorResult reflectorResult = GetReflectorResult(source, codeToExecute, false, createIfNotExists); 
     if (reflectorResult != null) 
     { 
     TypeConverter typeConverter = null; 
     PropertyInfo propertyInfo = reflectorResult.MemberInfo as PropertyInfo; 
     if (propertyInfo != null) 
     { 
      if (propertyInfo.CanWrite) 
      { 
      typeConverter = GetTypeConverter(propertyInfo); 

      ConversionResult conversionResult = ConvertValue(value, propertyInfo.PropertyType, typeConverter); 
      if (conversionResult.Success) 
      { 
       propertyInfo.SetValue(reflectorResult.PreviousValue, conversionResult.ConvertedValue, reflectorResult.MemberInfoParameters); 
      } 
      else 
      { 
       executed = false; 
       PentaLogger.LogVerbose("Invalid value: " + value); 
      } 
      } 
     } 
     else 
     { 
      FieldInfo fieldInfo = reflectorResult.MemberInfo as FieldInfo; 
      if (fieldInfo != null) 
      { 
      typeConverter = GetTypeConverter(fieldInfo); 
      ConversionResult conversionResult = ConvertValue(value, fieldInfo.FieldType, typeConverter); 
      if (conversionResult.Success) 
      { 
       fieldInfo.SetValue(reflectorResult.PreviousValue, conversionResult.ConvertedValue); 
      } 
      else 
      { 
       executed = false; 
       PentaLogger.LogVerbose("Invalid value: " + value); 
      } 
      } 
      else 
      { 
      // both property and field are invalid 
      executed = false; 
      } 
     } 
     } 
     else 
     { 
     executed = false; 
     } 

     return executed; 
    } 

    /// <summary> 
    /// Sets the "source" object to the "value" specified in "codeToExecute" 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="codeToExecute">Code that should be executed ex. 'Person.Age'</param> 
    /// <param name="value">Value to set the source+codeToExecute to.</param> 
    public static void RunDynamicCode(object source, String codeToExecute) 
    { 
     GetReflectorResult(source, codeToExecute, true, false); 
    } 

    /// <summary> 
    /// Executes the method on the "source" object with the passed parameters 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="methodName">Method to call</param> 
    /// <param name="parameters">Method Parameters</param> 
    public static object ExecuteMethod(object source, String methodName, object[] parameters) 
    { 
     if (parameters == null) 
     { 
     parameters = new object[0]; 
     } 

     MethodInfo[] methodInfos = GetMethods(source, methodName); 

     foreach (MethodInfo methodInfo in methodInfos) 
     { 
     object[] convertedParameters = GetParameters(methodInfo, parameters); 
     if (convertedParameters != null) 
     { 
      return methodInfo.Invoke(source, convertedParameters); 
     } 
     } 
     return null; 
    } 

    /// <summary> 
    /// Executes the method on the "source" object with the passed parameters 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="methodName">Method to call</param> 
    /// <param name="parameter">Method Parameter</param> 
    public static object ExecuteMethod(object source, String methodName, object parameter) 
    { 
     return ExecuteMethod(source, methodName, new object[] { parameter }); 
    } 

    /// <summary> 
    /// Executes the method on the "source" object with no parameters 
    /// </summary> 
    /// <param name="source">Object the code should be executed against</param> 
    /// <param name="methodName">Method to call</param> 
    public static object ExecuteMethod(object source, String methodName) 
    { 
     return ExecuteMethod(source, methodName, null); 
    } 

    /// <summary> 
    /// Copies all public properties and fields from source to target 
    /// </summary> 
    /// <param name="source"></param> 
    /// <param name="target"></param> 
    public static void CopyObject(object source, object target) 
    { 
     if (source != null && target != null) 
     { 
     Type targetType = target.GetType(); 
     Type sourceType = source.GetType(); 

     PropertyInfo[] properties = sourceType.GetProperties(DefaultBindings); 
     foreach (PropertyInfo sourceProperty in properties) 
     { 
      PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name, sourceProperty.PropertyType); 
      if (targetProperty != null && targetProperty.CanRead && targetProperty.CanWrite) 
      { 
      object value = sourceProperty.GetValue(source, null); 
      targetProperty.SetValue(target, value, null); 
      } 
     } 

     FieldInfo[] fields = sourceType.GetFields(DefaultBindings); 
     foreach (FieldInfo sourceField in fields) 
     { 
      FieldInfo targetField = targetType.GetField(sourceField.Name); 
      if (targetField != null && targetField.IsPublic) 
      { 
      object value = sourceField.GetValue(source); 
      targetField.SetValue(target, value); 
      } 
     } 
     } 
    } 

    /// <summary> 
    /// Convert the object to the correct type 
    /// </summary> 
    /// <param name="value">Value to convert</param> 
    /// <param name="type">Type to convert to</param> 
    /// <returns>Converted value</returns> 
    public static ConversionResult ConvertValue(object value, Type type, TypeConverter typeConverter) 
    { 
     ConversionResult conversionResult = new ConversionResult(); 
     conversionResult.Success = false; 
     if (value != null && type != null) 
     { 
     Type objectType = value.GetType(); 
     if (objectType == type) 
     { 
      conversionResult.Success = true; 
      conversionResult.ConvertedValue = value; 
     } 
     else 
     { 
      // If there is an explicit type converter use it 
      if (typeConverter != null && typeConverter.CanConvertFrom(objectType)) 
      { 
      try 
      { 
       conversionResult.ConvertedValue = typeConverter.ConvertFrom(value); 
       conversionResult.Success = true; 
      } 
      catch (FormatException) { } 
      catch (Exception e) 
      { 
       if (!(e.InnerException is FormatException)) 
       { 
       throw; 
       } 
      } 
      } 
      else 
      { 
      try 
      { 
       conversionResult.ConvertedValue = Convert.ChangeType(value, type, CultureInfo.CurrentCulture); 
       conversionResult.Success = true; 
      } 
      catch (InvalidCastException) { } 
      } 
     } 
     } 
     return conversionResult; 
    } 

    public static Boolean CanCreateObect(String classPath, Assembly assembly, params object[] parameters) 
    { 
     Boolean canCreate = false; 
     Type type = Type.GetType(classPath); 
     if (type == null) 
     { 
     String pathWithAssembly = classPath + ", " + assembly.FullName; 
     type = Type.GetType(pathWithAssembly); 
     } 

     if (type != null) 
     { 
     foreach (ConstructorInfo ci in type.GetConstructors()) 
     { 
      if (ci.IsPublic) 
      { 
      ParameterInfo[] constructorParameters = ci.GetParameters(); 
      if (constructorParameters.Length == parameters.Length) 
      { 
       for(Int32 i=0; i<constructorParameters.Length; i++) 
       {     
       object parameter = parameters[i]; 
       if(parameter == null) 
       { 
        continue; 
       } 

       ParameterInfo pi = constructorParameters[i]; 
       if (!pi.ParameterType.IsAssignableFrom(parameter.GetType())) 
       { 
        break; 
       } 
       } 
       canCreate = true; 
       break; 
      } 
      } 
     }  
     } 
     return canCreate; 
    } 

    public static object CreateObject(String classPath, Assembly assembly, params object[] parameters) 
    { 
     Type type = Type.GetType(classPath); 
     if (type == null) 
     { 
     String pathWithAssembly = classPath + ", " + assembly.FullName; 
     type = Type.GetType(pathWithAssembly); 
     } 

     if (type == null) 
     { 
     return null; 
     } 
     return Activator.CreateInstance(type, parameters); 
    } 
    #endregion 

    #region Private Methods 
    private static ReflectorResult GetReflectorResult(object source, String codeToExecute, bool getLastValue, bool createIfNotExists) 
    { 
     ReflectorResult result = new ReflectorResult(source); 

     try 
     { 
     // Split the code into usable fragments 
     String[] codeFragments = SplitCodeArray(codeToExecute); 
     for (Int32 i = 0; i < codeFragments.Length; i++) 
     { 
      // if the value is null we cannot go any deeper so don't waste your time 
      if (result.Value == null) 
      { 
      return result; 
      } 

      String codeFragment = codeFragments[i]; 
      result.PreviousValue = result.Value; 

      if (codeFragment.Contains("]")) 
      { 
      ProcessArray(result, codeFragment, createIfNotExists); 
      } 
      else if (codeFragment.Contains(")")) 
      { 
      ProcessMethod(result, codeFragment); 
      } 
      else 
      { 
      // For set properties we do not need the last value 
      bool retrieveValue = getLastValue; 
      if (!retrieveValue) 
      { 
       // If this is not the last one in the array, get it anyway 
       retrieveValue = i + 1 != codeFragments.Length; 
      } 
      ProcessProperty(result, codeFragment, retrieveValue); 
      } 
     } 
     } 
     catch (InvalidCodeFragmentException ex) 
     { 
     PentaLogger.LogVerbose("Invalid Property: '" + codeToExecute + "' Invalid Fragment: '" + ex.Message + "'"); 
     } 

     return result; 
    } 

    private static String[] SplitCodeArray(String codeToExecute) 
    { 
     List<String> items = new List<String>(); 

     Int32 parenAndbracketCount = 0; 
     String buffer = ""; 
     foreach (Char c in codeToExecute.ToCharArray()) 
     { 
     if (c == '.') 
     { 
      if (buffer.Length > 0) 
      { 
      items.Add(buffer); 
      buffer = ""; 
      } 
      continue; 
     } 
     else if (c == '[') 
     { 
      parenAndbracketCount++; 
      if (buffer.Length > 0) 
      { 
      items.Add(buffer); 
      } 
      buffer = c.ToString(); 
     } 
     else if (c == ']' || c == ')') 
     { 
      parenAndbracketCount--; 
      buffer += c; 
      if (buffer.Length > 0) 
      { 
      items.Add(buffer); 
      buffer = ""; 
      } 
     } 
     else if (Char.IsWhiteSpace(c) || Char.IsControl(c)) 
     { 
      if (parenAndbracketCount == 0) 
      { 
      // Skip it 
      continue; 
      } 
      else 
      { 
      buffer += c; 
      } 
     } 
     else if (c == '(') 
     { 
      parenAndbracketCount++; 
      buffer += c; 
     } 
     else 
     { 
      buffer += c; 
     } 
     } 
     if (buffer.Length > 0) 
     { 
     items.Add(buffer); 
     } 
     return items.ToArray(); 
    } 

    private static object[] GetParameters(String codeFragment, MemberInfo memberInfo) 
    { 
     String parameters = SplitParametersFromMethod(codeFragment); 
     if (String.IsNullOrEmpty(parameters)) 
     return new object[0]; 

     object[] parameterArray = parameters.Split(','); 
     return GetParameters(memberInfo, parameterArray); 
    } 

    private static object[] GetParameters(MemberInfo memberInfo, object[] parameterArray) 
    { 
     ParameterInfo[] parameterInfo = null; 
     TypeConverter typeConverter = null; 

     PropertyInfo propertyInfo = memberInfo as PropertyInfo; 
     if (propertyInfo != null) 
     { 
     parameterInfo = propertyInfo.GetIndexParameters(); 
     typeConverter = GetTypeConverter(parameterInfo[0]); 
     } 
     else 
     { 
     MethodInfo methodInfo = memberInfo as MethodInfo; 
     if (methodInfo != null) 
     { 
      parameterInfo = methodInfo.GetParameters(); 
     } 
     } 

     if (parameterInfo == null) 
     { 
     return null; 
     } 

     object[] returnParameters = new object[parameterInfo.Length]; 
     for (Int32 i = 0; i < parameterArray.Length; i++) 
     { 
     ConversionResult converstionResult = ConvertValue(parameterArray[i], parameterInfo[i].ParameterType, typeConverter); 
     if (converstionResult.Success) 
     { 
      returnParameters[i] = converstionResult.ConvertedValue; 
     } 
     else 
     { 
      return null; 
     } 
     } 
     return returnParameters; 
    } 

    private static TypeConverter GetTypeConverter(MemberInfo memberInfo, Type targetType) 
    { 
     object[] typeConverters = memberInfo.GetCustomAttributes(typeof(TypeConverterAttribute), true); 
     if (typeConverters.Length > 0) 
     { 
     TypeConverterAttribute typeConverterAttribute = (TypeConverterAttribute)typeConverters[0]; 
     Type typeFromName = Type.GetType(typeConverterAttribute.ConverterTypeName); 
     if ((typeFromName != null) && typeof(TypeConverter).IsAssignableFrom(typeFromName)) 
     { 
      return (TypeConverter)Activator.CreateInstance(typeFromName); 
     } 
     } 
     return TypeDescriptor.GetConverter(targetType); 
    } 

    private static TypeConverter GetTypeConverter(PropertyInfo propertyInfo) 
    { 
     return GetTypeConverter(propertyInfo, propertyInfo.PropertyType); 
    } 

    private static TypeConverter GetTypeConverter(FieldInfo fieldInfo) 
    { 
     return GetTypeConverter(fieldInfo, fieldInfo.FieldType); 
    } 

    private static TypeConverter GetTypeConverter(ParameterInfo parameterInfo) 
    { 
     return GetTypeConverter(parameterInfo.Member, parameterInfo.ParameterType); 
    } 

    private static ArrayDefinition GetArrayDefinition(object value, String codeToExecute) 
    { 
     // All IList classes have an Item property except for System.Array. 
     List<MemberInfo> retrieveMemberInfos = new List<MemberInfo>(); 
     foreach (PropertyInfo propertyInfo in value.GetType().GetProperties(DefaultBindings)) 
     { 
     if (propertyInfo.Name == "Item") 
     { 
      retrieveMemberInfos.Add(propertyInfo); 
     } 
     } 

     if (retrieveMemberInfos.Count == 0) 
     { 
     // We didn't find any Item properties so this is probably an Array. Use the GetValue method 
     foreach (MethodInfo methodInfo in value.GetType().GetMethods(DefaultBindings)) 
     { 
      if (methodInfo.Name == "GetValue") 
      { 
      retrieveMemberInfos.Add(methodInfo); 
      } 
     } 
     } 

     // Some members have overloaded this[] methods. Find the correct method. 
     foreach (MemberInfo memberInfo in retrieveMemberInfos) 
     { 
     object[] parameters = GetParameters(codeToExecute, memberInfo); 
     if (parameters != null) 
     { 
      ArrayDefinition arrayDefinition = new ArrayDefinition(); 
      arrayDefinition.Parameters = parameters; 
      arrayDefinition.RetrieveMemberInfo = memberInfo; 
      return arrayDefinition; 
     } 
     } 
     return null; 
    } 

    private static void ProcessArray(ReflectorResult result, String codeFragment, Boolean createIfNotExists) 
    { 
     Int32 failCount = 0; 
     ArrayDefinition arrayDefinition = GetArrayDefinition(result.Value, codeFragment); 
     if (arrayDefinition != null) 
     { 
     // If this is anything but System.Array we need to call a Property 
     PropertyInfo propertyInfo = arrayDefinition.RetrieveMemberInfo as PropertyInfo; 
     if (propertyInfo != null) 
     { 
     SetPropertyInfoValue: 
      try 
      { 
      object value = propertyInfo.GetValue(result.Value, arrayDefinition.Parameters); 
      result.SetResult(value, propertyInfo, arrayDefinition.Parameters); 
      } 
      catch (TargetInvocationException ex) 
      { 
      failCount++; 
      if (ex.InnerException is ArgumentOutOfRangeException && failCount == 1 && createIfNotExists) 
      { 
       if (CreateArrayItem(result, arrayDefinition)) 
       { 
       goto SetPropertyInfoValue; 
       } 
      } 

      // Tried to fix it but failed. Blow up 
      result.Clear(); 
      throw new InvalidCodeFragmentException(codeFragment); 
      } 
     } 
     else 
     { 
      // System.Array has a Method to call 
      MethodInfo methodInfo = arrayDefinition.RetrieveMemberInfo as MethodInfo; 
      if (methodInfo != null) 
      { 
      try 
      { 
       // We can't support dynamically creating array items 
       object value = methodInfo.Invoke(result.Value, arrayDefinition.Parameters); 
       result.SetResult(value, methodInfo, arrayDefinition.Parameters); 
      } 
      catch (TargetInvocationException) 
      { 
       result.Clear(); 
       throw new InvalidCodeFragmentException(codeFragment); 
      } 
      } 
     } 
     } 
     else 
     { 
     result.Clear(); 
     throw new InvalidCodeFragmentException(codeFragment); 
     } 
    } 

    private static Boolean CreateArrayItem(ReflectorResult result, ArrayDefinition arrayDefinition) 
    { 
     Type resultType = result.Value.GetType(); 
     Type containedType = null; 
     if (resultType.IsArray) 
     { 
     containedType = resultType.GetElementType(); 
     } 
     else 
     { 
     containedType = resultType.GetGenericArguments()[0]; 
     } 

     object newInstance = Activator.CreateInstance(containedType); 
     if (!resultType.IsArray) 
     { 
     MethodInfo[] methods = GetMethods(result.Value, "Insert"); 
     foreach (MethodInfo methodInfo in methods) 
     { 
      object[] temp = new object[arrayDefinition.Parameters.Length + 1]; 
      arrayDefinition.Parameters.CopyTo(temp, 0); 
      temp[arrayDefinition.Parameters.Length] = newInstance; 

      object[] parameters = GetParameters(methodInfo, temp); 
      if (parameters != null) 
      { 
      methodInfo.Invoke(result.Value, parameters); 
      return true; 
      } 
     } 
     } 
     return false; 
    } 

    private static void ProcessProperty(ReflectorResult result, String codeFragment, bool retrieveValue) 
    { 
     // This is just a regular property 
     PropertyInfo propertyInfo = result.Value.GetType().GetProperty(codeFragment, DefaultBindings); 
     if (propertyInfo != null) 
     { 
     object value = result.Value; 
     if (retrieveValue) 
     { 
      value = propertyInfo.GetValue(result.Value, null); 
      result.SetResult(value, propertyInfo, null); 
     } 
     result.SetResult(value, propertyInfo, null); 
     } 
     else 
     { 
     // Maybe it is a field 
     FieldInfo fieldInfo = result.Value.GetType().GetField(codeFragment, DefaultBindings); 

     if (fieldInfo != null) 
     { 
      object value = result.Value; 
      if (retrieveValue) 
      { 
      value = fieldInfo.GetValue(result.Value); 
      } 
      result.SetResult(value, fieldInfo, null); 
     } 
     else 
     { 
      // This item is missing, log it and set the value to null 
      result.Clear(); 
      throw new InvalidCodeFragmentException(codeFragment); 
     } 
     } 
    } 

    private static void ProcessMethod(ReflectorResult result, String codeFragment) 
    { 
     // This is just a regular property 
     String methodName = codeFragment.Substring(0, codeFragment.IndexOf('(')); 
     MethodInfo[] methodInfos = GetMethods(result.Value, methodName); 

     foreach (MethodInfo methodInfo in methodInfos) 
     { 
     object[] parameters = GetParameters(codeFragment, methodInfo); 
     if (parameters != null) 
     { 
      object value = methodInfo.Invoke(result.Value, parameters); 
      result.SetResult(value, null, null); 
      break; 
     } 
     } 
    } 

    private static String SplitParametersFromMethod(String codeFragment) 
    { 
     char startCharacter = '['; 
     char endCharacter = ']'; 

     if (codeFragment.EndsWith(")", StringComparison.CurrentCulture)) 
     { 
     // This is a function 
     startCharacter = '('; 
     endCharacter = ')'; 
     } 

     Int32 startParam = codeFragment.IndexOf(startCharacter) + 1; 
     if (startParam < 1) 
     return null; 

     Int32 endParam = codeFragment.IndexOf(endCharacter); 
     if (endParam < 0) 
     return null; 

     return codeFragment.Substring(startParam, endParam - startParam).Trim(); 
    } 

    private static MethodInfo[] GetMethods(object value, String methodName) 
    { 
     if (String.IsNullOrEmpty(methodName)) 
     { 
     throw new ArgumentNullException("methodName"); 
     } 

     if (value == null) 
     { 
     return new MethodInfo[0]; 
     } 

     List<MethodInfo> methodInfos = new List<MethodInfo>(); 
     foreach (MethodInfo methodInfo in value.GetType().GetMethods(DefaultBindings)) 
     { 
     if (methodInfo.Name == methodName) 
     { 
      methodInfos.Add(methodInfo); 
     } 
     } 
     return methodInfos.ToArray(); 
    } 
    #endregion 

    #region Helper Classes 
    private class ArrayDefinition 
    { 
     public MemberInfo RetrieveMemberInfo { get; set; } 

     public object[] Parameters { get; set; } 
    } 

    private class ReflectorResult 
    { 
     public ReflectorResult(object startValue) 
     { 
     SetResult(startValue, null, null); 
     } 
     public MemberInfo MemberInfo { get; private set; } 
     public object[] MemberInfoParameters { get; private set; } 
     public object PreviousValue { get; set; } 
     public object Value { get; private set; } 

     public void SetResult(object value, MemberInfo memberInfo, object[] memberInfoParameters) 
     { 
     Value = value; 
     MemberInfo = memberInfo; 
     MemberInfoParameters = memberInfoParameters; 
     } 

     public void Clear() 
     { 
     MemberInfo = null; 
     Value = null; 
     PreviousValue = null; 
     } 
    } 

    [Serializable] 
    [SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic")] 
    [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] 
    private class InvalidCodeFragmentException : Exception 
    { 
     public InvalidCodeFragmentException(String invalidFragment) 
     : base(invalidFragment) 
     { 

     } 
    } 
    #endregion 
    } 
} 
+0

이것은 효과가 있을지 모르지만 .NET 1.1에서는 전혀 컴파일되지 않은 것 같습니다. 나머지 프로젝트와 호환되도록 내가 현재 사용하고있는 것입니다. 그래도 재미있을 것 같습니다. – Jeff

+2

@ShaunBowe +1. 하지만 당신이'ConversionResult' 정의 –

+1

@ShaunBowe를 잊어 버린 것 같아요, 당신은 ConversionResult 클래스를 추가해야합니다. – Justin

관련 문제