c#和LINQ,其中集合成员的property-name通过函数传递

时间:2012-06-29 02:04:29

标签: c# linq generics parameters

与往常一样,帮助/评论的想法总是受到赞赏,并为我的编程天真而道歉。

我正在尝试创建一个广泛适用的功能,可用于涉及块随机化的未来研究。 patientDataCollection的每个成员都有一个名为的东西,例如interventionArm,givenDrugX或类似的东西。该功能旨在(伪)随机分配到研究的一个分支,具体取决于块大小 - 也就是说,如果块大小为8,则将4分配给治疗,4分配给控制(不治疗)。

到目前为止的代码:

 public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, string allocationPropertyName)
 {
    int remainingAllocations = blockSize - patientDataCollection.Count();
    if (remainingAllocations <= 0) throw new Exception("All alocations within block accounted for");
    var p = typeof(T).GetProperty(allocationPropertyName);

    int remainingInterventions = blockSize/2 - patientDataCollection.Count(c => c.p);
    double Pintervention = (double)remainingInterventions / (double)remainingAllocations;
    double rdm = new Random().NextDouble();
    return (rdm <= Pintervention);
 }

这当然是有缺陷的逻辑,因为变量p与linq语句patientDataCollection.Count(c =&gt; c.p)中引用的c.p无关。很明显,这个陈述只是计算所有具有真实价值的元素。

ASP是4.0。任何人都可以看到如何实现这个

3 个答案:

答案 0 :(得分:2)

您可以将Func<T, bool>传递给您的方法,用于计算。

public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, Func<T,bool> predicate) 
{ 
    int remainingAllocations = blockSize - patientDataCollection.Count(); 
    if (remainingAllocations == 0) throw new Exception("All alocations within block accounted for"); 
    int remainingInterventions = blockSize/2 - patientDataCollection.Count(predicate); 
    double Pintervention = remainingInterventions / remainingAllocations; 
    double rdm = new Random().NextDouble(); 
    return (rdm <= Pintervention); 
}

使用示例如下:

var result = nextAllocation(10, collection, c=>c.interventionArm);

答案 1 :(得分:1)

您可以使用reflection获取该属性的值:

int remainingInterventions = blockSize/2 - 
    patientDataCollection.Count(c => (bool)p.GetValue(c,null));

添加错误检查。

答案 2 :(得分:0)

尝试使用表达式

public static class ExpressionCreator
{
    public static Func<T, TProperty> CreatePropertyAccessExpression<T, TProperty>(string propertyName)
    {
        var tType = typeof (T);
        var property = tType.GetProperty(propertyName);
        var parameterExpression = Expression.Parameter(tType);
        var memberAccessExpression = Expression.MakeMemberAccess(parameterExpression, property);
        var lambda = Expression.Lambda<Func<T, TProperty>>(memberAccessExpression, parameterExpression);
        return lambda.Compile();
    }
}

使用示例:

    public class A
    {
        public bool Thing1 { get; set; }
        public bool Thing2 { get; set; }
    }

    static void Main(string[] args)
    {
        var @as = new A[10];
        for(var i = 0; i < @as.Length; i+=2)
        {
            @as[i] = new A {Thing1 = true};
            @as[i + 1] = new A {Thing2 = i%4 == 0};
        }

        var thing1Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing1");
        var thing2Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing2");
        Console.WriteLine(@as.Count(thing1Expression));
        Console.WriteLine(@as.Count(thing2Expression));
        Console.ReadLine();
    }