Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何删除在使用属性/字段将自身显示为字符串方面存在差异的重复代码?_C#_Design Patterns_C# 4.0 - Fatal编程技术网

C# 如何删除在使用属性/字段将自身显示为字符串方面存在差异的重复代码?

C# 如何删除在使用属性/字段将自身显示为字符串方面存在差异的重复代码?,c#,design-patterns,c#-4.0,C#,Design Patterns,C# 4.0,我有两种非常相似的扩展方法。我想用pattern之类的方法删除重复的代码,但实际上无法让它正常工作 代码如下所示: public static String GetPublicPropertiesAsString( this Object @this ) { return @this.GetType().GetProperties() .Select( propertyInfo => {

我有两种非常相似的扩展方法。我想用pattern之类的方法删除重复的代码,但实际上无法让它正常工作

代码如下所示:

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 );
}
上面重复的代码能被重构掉吗


注意:JoinaString、RemoveAll和FormatWith是我自己的扩展方法。

我会将中间代码重构为一个接受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));
    }

是的,它可以。通过使用泛型以及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));
}

它可能会删除重复的代码,但也会将原始声明性代码重构为命令式代码,这会降低可读性。@Martin好吧,我们可以通过为每个,但老实说,尤其是在私有实现方法方面,我不确定是否值得就FP与其他人之间的压力进行辩论。只要它有效,等等。。。。