C# 重复的方法调用模型的不同属性
有可能简化这段代码吗?我正在将数据从值列表转换为同一对象。在每个方法中,要求和的属性都会更改 属性每次都遵循相同的命名约定(C# 重复的方法调用模型的不同属性,c#,design-patterns,C#,Design Patterns,有可能简化这段代码吗?我正在将数据从值列表转换为同一对象。在每个方法中,要求和的属性都会更改 属性每次都遵循相同的命名约定(paios或pa),后跟(InUse或suportiuse)。我知道在JavaScript中我可以生成字符串并计算字符串,但据我所知,在C#中没有类似的东西 公共类公司价值 { 公共交通; 公共int Papc; 公共丘疹; 公共国际环境影响报告书; 公共国际Pd; 公共智力下降; 上市公司价值消费(上市公司) { Paios=companys.Sum(x=>x.paios
paios
或pa
),后跟(InUse
或suportiuse
)。我知道在JavaScript中我可以生成字符串并计算字符串,但据我所知,在C#中没有类似的东西
公共类公司价值
{
公共交通;
公共int Papc;
公共丘疹;
公共国际环境影响报告书;
公共国际Pd;
公共智力下降;
上市公司价值消费(上市公司)
{
Paios=companys.Sum(x=>x.paiosuse);//您可以使用反射来获取属性,然后找到要使用的属性
public class CompanyLicValues
{
public int Paios { get; private set; }
public int Papc { get; private set; }
public CompanyLicValues SumInUse(List<VwCompany> companies)
{
SumDynamically(companies, "InUse");
return this; return this;
}
public CompanyLicValues SumSupportUsed(List<VwCompany> companies)
{
SumDynamically(companies, "SupportInUse");
return this;
}
private void SumDynamically(IReadOnlyCollection<VwCompany> companies, string propertySuffix)
{
Paios = SumProperty(companies, $"{nameof(Paios)}{propertySuffix}");
Papc = SumProperty(companies, $"{nameof(Papc)}{propertySuffix}");
}
private static int SumProperty(IEnumerable<VwCompany> companies, string propertyName)
{
var properties = typeof(VwCompany).GetProperties(); //cache properties
var p = properties.FirstOrDefault(x => x.Name == propertyName && x.GetMethod.ReturnType == typeof(int));
if (p is null) throw new Exception("Property Not found");
return companies.Sum(x => (int)p.GetValue(x));
}
}
公共类公司价值
{
公共整数对{get;私有集;}
public int Papc{get;private set;}
上市公司价值消费(上市公司)
{
Sumse(公司,“因努斯”);
还这个,还这个,;
}
上市公司使用的价值(上市公司)
{
SumDynamics(公司,“支持使用”);
归还这个;
}
私有资产(IReadOnlyCollection公司、字符串属性uffix)
{
Paios=SumProperty(公司,$“{nameof(Paios)}{propertySuffix}”);
Papc=SumProperty(公司,$“{nameof(Papc)}{propertySuffix}”);
}
私有静态int-SumProperty(IEnumerable公司,字符串propertyName)
{
var properties=typeof(VwCompany).GetProperties();//缓存属性
var p=properties.FirstOrDefault(x=>x.Name==propertyName&&x.GetMethod.ReturnType==typeof(int));
如果(p为null)抛出新异常(“未找到属性”);
返回公司.Sum(x=>(int)p.GetValue(x));
}
}
首先,将您的类更改为使用属性而不是字段,因为这样可以在将来提供更大的灵活性,因为您可以自定义getter/setter逻辑。此外,还可以使setter私有化
或内部
允许您返回数据的只读视图
对于您的问题,您需要使用Linq的Aggregate
扩展方法,但需要提供一个基于反射的自定义累加器,如下所示:
public class GenericAccumulator<TAccumulator,TItem>
{
private readonly TAccumulator accumulator;
private readonly IReadOnlyList<(PropertyInfo itemProperty, PropertyInfo accumulatorProperty)> propertyMap;
public GenericAccumulator( TAccumulator accumulator )
{
this.accumulator = accumulator;
PropertyInfo[] accumulatorProperties = typeof(TAccumulator).GetProperties();
Dictionary<String,PropertyInfo> itemPropertiesByName = typeof(TItem)
.GetProperties()
.ToDictionary( pi => pi.Name );
List<(PropertyInfo itemProperty, PropertyInfo accumulatorProperty)> itemProperties = new List<(PropertyInfo itemProperty, PropertyInfo accumulatorProperty)>();
foreach( PropertyInfo accumulatorProperty in accumulatorProperties )
{
String expectedItemPropertyName = accumulatorProperty.Name + "InUse";
if( itemPropertiesByName.TryGetValue( expectedItemPropertyName, out PropertyInfo itemProperty )
{
itemProperties.Add( ( itemProperty, accumulatorProperty ) );
}
}
this.propertyMap = itemProperties;
}
public GenericAccumulator<TAccumulator,TItem> Next( GenericAccumulator<TAccumulator,TItem> self, TItem item )
{
// Ignore `self`. It's needed for compatibility with Linq's `Func` parameter.
foreach( PropertyInfo itemProperty in this.itemProperties )
{
PropertyInfo accumulatorProperty = this.propertyMap[ itemProperty ];
Int32 itemPropertyValue = (Int32)itemProperty.GetValue( item, null );
Int32 accumulatorPropertyValue = (Int32)accumulatorProperty.GetValue( this.accumulator, null );
accumulatorPropertyValue += itemPropertyValue;
accumulatorProperty.SetValue( this.accumulator, null, accumulatorPropertyValue );
}
}
}
公共类泛型累加器
{
专用只读累加器累加器;
私有只读IReadOnlyList属性映射;
公共通用累加器(TACCumerator累加器)
{
这个。累加器=累加器;
PropertyInfo[]累加器Properties=typeof(taCumulator).GetProperties();
Dictionary itemPropertiesByName=typeof(TItem)
.GetProperties()
.ToDictionary(pi=>pi.Name);
List itemProperties=新列表();
foreach(属性信息累加器属性信息累加器属性中的属性)
{
字符串expectedItemPropertyName=AccumeratorProperty.Name+“InUse”;
if(itemPropertiesByName.TryGetValue(expectedItemPropertyName,out PropertyInfo itemProperty)
{
添加((itemProperty,累加器属性));
}
}
this.propertyMap=itemProperties;
}
公共通用累加器Next(通用累加器自身,滴度项)
{
//忽略“self”。它是与Linq的“Func”参数兼容所必需的。
foreach(PropertyInfo itemProperty在this.itemProperties中)
{
PropertyInfo AccumeratorProperty=this.propertyMap[itemProperty];
Int32 itemPropertyValue=(Int32)itemProperty.GetValue(item,null);
Int32 AccumeratorPropertyValue=(Int32)AccumeratorProperty.GetValue(this.Accumerator,null);
累加器属性值+=项目属性值;
AccumeratorProperty.SetValue(this.Accumerator,null,AccumeratorPropertyValue);
}
}
}
这样使用:
using System.Linq;
class CompanyLicenseAccumulator
{
public Int32 Paios { get; set; }
public Int32 Papc { get; set; }
public Int32 Paplus { get; set; }
// etc
}
static void Foo()
{
List<vwCompany> companies = ...
GenericAccumulator<CompanyLicenseAccumulator,CompanyLicense> ca = new GenericAccumulator<CompanyLicenseAccumulator,CompanyLicense>( new CompanyLicenseAccumulator() );
CompanyLicenseAccumulator summedValues = companies
.Aggregate( ca ), ca.Next );
}
使用System.Linq;
类公司许可证累积器
{
公共Int32 Paios{get;set;}
公共Int32 Papc{get;set;}
公共Int32 Paplus{get;set;}
//等
}
静态void Foo()
{
上市公司=。。。
GenericAccumulator ca=新的GenericAccumulator(新公司LicenseAccumulator());
CompanyLicenseAccumerator summedValues=公司
。骨料(ca),约次之);
}
公共类公司价值
{
私人上市公司;
上市公司价值(上市公司)
{
_公司=公司;
}
公共国际派奥
{
返回_companys.Sum(x=>x.paiouse);
}
公共int Papc
{
收益_companys.Sum(x=>x.papcInUse);
}
}
试试这个公共类公司价值
public class CompanyLicValues
{
List<vwCompany> _companies;
public CompanyLicValues(List<vwCompany> companies)
{
_companies=companies;
}
public int Paios
{
return companies.Sum(x => x.paiosInUse);
}
public int Papc
{
return companies.Sum(x => x.papcInUse);
}
}
{
上市公司;
上市公司价值(上市公司)
{
_公司=公司;
}
公共国际派奥
{
返回公司。总和(x=>x.paiouse);
}
公共int Papc
{
返回公司。总和(x=>x.papcInUse);
}
}
试试这个你所说的“被求和的属性改变”是什么意思?你可以只使用一个函数和另一个参数来选择要求和的属性。大致如下:public CompanyLicValues Sum(List companys,Func propSelector)
public class CompanyLicValues
{
List<vwCompany> _companies;
public CompanyLicValues(List<vwCompany> companies)
{
_companies=companies;
}
public int Paios
{
return companies.Sum(x => x.paiosInUse);
}
public int Papc
{
return companies.Sum(x => x.papcInUse);
}
}
public class CompanyLicValues
{
List<vwCompany> _companies;
public CompanyLicValues(List<vwCompany> companies)
{
_companies=companies;
}
public int Paios
{
return companies.Sum(x => x.paiosInUse);
}
public int Papc
{
return companies.Sum(x => x.papcInUse);
}
}