Как удалить повторяющийся код, который отличается использованием свойств / полей для отображения себя в виде строк? - PullRequest
3 голосов
/ 27 сентября 2010

У меня есть два метода расширения, которые очень похожи. Я хотел бы удалить дубликаты кода с шаблоном «дыра в середине» и т. П., Но не могу заставить его работать.

Код выглядит так:

public static String GetPublicPropertiesAsString( this Object @this )
{
    return @this.GetType().GetProperties()
        .Select( propertyInfo =>
                        {
                            var propertyValue = propertyInfo.GetValue( obj: @this,
                                                                    invokeAttr: BindingFlags.Public,
                                                                    binder: null,
                                                                    index: null,
                                                                    culture: null );

                            var propertyValueAsString = propertyValue != null ? propertyValue.ToString().RemoveAll( "00:00:00" ) : "[null]";

                            return "{0}: {1}".FormatWith( propertyInfo.Name, propertyValueAsString );
                        } ).JoinAsString( Environment.NewLine );
}

public static String GetFieldsAsString( this Object @this )
{
    return @this.GetType().GetFields()
        .Select( fieldInfo =>
                        {
                            var fieldValue = fieldInfo.GetValue( @this );

                            var fieldValueAsString = fieldValue != null ? fieldValue.ToString().RemoveAll( "00:00:00" ) : "[null]";

                            return "{0}: {1}".FormatWith( fieldInfo.Name, fieldValueAsString );
                        } ).JoinAsString( Environment.NewLine );
}

Может ли повторяющийся код, указанный выше, быть подвергнут рефакторингу?

Примечание: JoinAsString, RemoveAll и FormatWith - мои собственные методы расширения.

Ответы [ 2 ]

3 голосов
/ 27 сентября 2010

Да, это возможно. При использовании обобщений и того факта, что PropertyInfo и FieldInfo происходят из MemberInfo

Примерно так:

static string GetAsString<T>
    (object @this, Func<T, object> getter) where T : MemberInfo
{
  return @this.GetType().GetMembers(/* binding flags */).OfType<T>().Select(
    x => 
    {
      var value = getter(x);
      var valueAsString = value != null ? value.ToString().
           RemoveAll( "00:00:00" ) : "[null]";
      return "{0}: {1}".FormatWith( x.Name, valueAsString );
    }).JoinAsString();
}

Теперь подключите:

public static String GetPublicPropertiesAsString( this Object @this )
{
  return GetAsString<PropertyInfo>(@this, x => x.GetValue(@this, null));
}

public static String GetPublicFieldsAsString( this Object @this )
{
  return GetAsString<FieldInfo>(@this, x => x.GetValue(@this));
}
0 голосов
/ 27 сентября 2010

Я бы преобразовал этот средний код в один метод, который принимает MemberInfo[] и выполняет переключение на тип члена.Не проверено, но:

    private static string GetMembersAsString(object @this, MemberInfo[] members)
    {
        var sb = new StringBuilder();
        for (int i = 0; i < members.Length; i++)
        {
            var member = members[i];
            if (i != 0) sb.AppendLine();
            object value;
            switch(member.MemberType) {
                case MemberTypes.Field:
                    value = ((FieldInfo)member).GetValue(@this);
                    break;
                case MemberTypes.Property:
                    value = ((PropertyInfo)member).GetValue(@this, null);
                    break;
                default:
                    throw new NotSupportedException(member.MemberType.ToString());
            }
            string s = value == null ? "[null]" : value.ToString().RemoveAll("00:00:00");
            sb.Append(member.Name).Append(" = ").Append(s);
        }
        return sb.ToString();
    }
    public static String GetPublicPropertiesAsString(this Object @this)
    {
        return GetMembersAsString(@this, @this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance));
    }

    public static String GetFieldsAsString(this Object @this)
    {
        return GetMembersAsString(@this, @this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance));
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...