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 - Fatal编程技术网

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); 
        }   
    }