C# 如何删除在使用属性/字段将自身显示为字符串方面存在差异的重复代码?
我有两种非常相似的扩展方法。我想用pattern之类的方法删除重复的代码,但实际上无法让它正常工作 代码如下所示: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 => {
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与其他人之间的压力进行辩论。只要它有效,等等。。。。