鉴于以下内容
class MyClass
{
private Expression<Func<SomeEntity, int>> _orderBy;
public MyClass(Expression<Func<SomeEntity, int>> orderBy)
{
_orderBy = orderBy;
}
public List<SomeEntity> Fetch()
{
return DbContext.Set<SomeEntity>().OrderBy(_orderBy).ToList();
}
}
// A function that creates an orderBy expression
Expression<Func<SomeEntity, int>> SomeFunction()
{
// r is a local variable for the sake of simplicity,
// actually it is a global static variable.
Random r = new Random();
int seed = r.nextInt();
// s.SomeProperty XOR seed, a simple random sorting method
return s => (s.SomeProperty & ~seed) | (~s.SomeProperty & seed);
}
执行代码
var myClass = new MyClass( SomeFunction() );
List<SomeEntity> someList = myClass.Fetch();
Thread.Sleep(100000);
List<SomeEntity> anotherList = myClass.Fetch();
每次调用Fetch()时,都必须返回一个随机排序的列表。问题是,每次调用Fetch()时都不会调用seed = r.nextInt()
。每次调用Fetch()
时,如何确保生成新种子?
答案 0 :(得分:2)
只需将调用r.Next()移动到您的委托中即可。下面的代码(因为我不想实际订购任何东西,从你的代码中有点愚蠢)每次返回不同的数字。对不起,变量名称很差......
仅供参考,变量r
从方法SomeFunction()
升级到堆上,并且会在任何时候使用Expression&gt;被叫。有关闭包的更多信息,请参阅This question and the link in the answer。
编辑:我已将随机数生成移动到自己的类似乎有效......
internal class MyClass {
private Expression<Func<string, int>> _aProperty;
public MyClass(Expression<Func<string, int>> aProperty) {
_aProperty = aProperty;
}
public int Fetch() {
var something = _aProperty.Compile();
return something("doesn't matter");
}
}
public class DoubleUp {
private Random r = new Random();
private int currentValue;
public int A { get { return currentValue; } }
public int B { get { int tmp = currentValue; currentValue = r.Next(); return tmp; } }
public DoubleUp() {
currentValue = r.Next();
}
}
internal class Program {
private static Expression<Func<string, int>> SomeFunction() {
DoubleUp d = new DoubleUp();
return s => (d.A - d.B);
}
private static void Main(string[] args) {
var myClass = new MyClass(SomeFunction());
Console.WriteLine(myClass.Fetch());
Console.WriteLine(myClass.Fetch());
Console.WriteLine(myClass.Fetch());
Console.ReadLine();
}
}
答案 1 :(得分:0)
一种可能的解决方案是传入一个工厂函数,该函数通过函数而不是函数本身生成订单,现在每次使用新种子调用Expression<Func<SomeEntity, int>>
时,它都会生成一个新的Fetch()
。 / p>
class MyClass
{
Func<Expression<Func<SomeEntity, int>>> _orderByFactory;
public MyClass(Func<Expression<Func<SomeEntity, int>>> orderByFactory)
{
_orderByFactory = orderByFactory;
}
public List<SomeEntity> Fetch()
{
var orderBy = _orderByFactory();
return DbContext.Set<SomeEntity>().OrderBy(orderBy).ToList();
}
}
//...
// Moved r out of the function as it needs to be outside for it to work.
static Random r = new Random();
static Expression<Func<SomeEntity, int>> SomeFunction()
{
int seed = r.Next();
// s.SomeProperty XOR seed, a simple random sorting method
return s => (s.SomeProperty & ~seed) | (~s.SomeProperty & seed);
}
//...
var myClass = new MyClass(SomeFunction); //<--Notice the removed parenthesis
List<SomeEntity> someList = myClass.Fetch();
Thread.Sleep(100000);
List<SomeEntity> anotherList = myClass.Fetch();
答案 2 :(得分:0)
使表达式成为每次调用Fetch时调用以获取新Orderby的Func:
class MyClass
{
private Func<Expression<Func<SomeEntity, int>>> _orderByFactory;
public MyClass(Func<Expression<Func<SomeEntity, int>>> orderByFactory)
{
_orderByFactory = orderByFactory;
}
public List<SomeEntity> Fetch()
{
var orderBy = _orderByFactory();
return DbContext.Set<SomeEntity>().OrderBy(orderBy).ToList();
}
}
呼叫变为
var myClass = new MyClass( () => SomeFunction() );
List<SomeEntity> someList = myClass.Fetch();
答案 3 :(得分:0)
问题是您只需拨打SomeFunction
一次即可设置种子。并且您无法在Expression中重置种子,因为表达式不能包含函数体。
另一种方法是使用4个字节的新Guid作为伪随机数生成器:
// A function that creates an orderBy expression
Expression<Func<int, int>> SomeFunction()
{
// Take 4 bytes from a new Guid and turn it into a 32-bit integer
return s=> BitConverter.ToInt32(Guid.NewGuid().ToByteArray(),0);
}
答案 4 :(得分:0)
鉴于你的问题陈述:
每次调用Fetch()时,都必须返回一个随机排序的列表。
在我看来,你是在思考过度的事情。为什么你不能做一些简单的事情:
class MyClass
{
private static Random rng = new Random() ;
public List<SomeEntity> Fetch()
{
return DbContext.Set<SomeEntity>()
.Cast<SomeEntity>()
.OrderBy( x => rng.Next() )
.ToList()
;
}
}