我正在阅读有关缓存和记忆的一些文章,以及如何使用委托和泛型轻松实现它.语法非常简单,实现起来非常简单,但我觉得由于重复性,应该可以基于属性生成代码,而不必反复编写相同的管道代码.
假设我们从默认示例开始:
class Foo
{
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
Run Code Online (Sandbox Code Playgroud)
然后记住这个:
// Let's say we have a utility class somewhere with the following extension method:
// public static Func<TResult> Memoize<TResult>(this Func<TResult> f)
class Foo
{
public Func<int,int> Fibonacci = fib;
public Foo()
{
Fibonacci = Fibonacci.Memoize();
}
public int fib(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
Run Code Online (Sandbox Code Playgroud)
我想,一旦找到一个匹配其中一个Memoize扩展方法的标记方法,那么只需要创建一个代码生成器就可以更简单.因此,我可以添加一个属性,而不是编写这个管道代码:
class Foo
{ …
Run Code Online (Sandbox Code Playgroud) 给定下面的lambda表达式,其中省类型包含公共属性"byte CountryId"和包含公共属性"byte Id"的Country类型.
Expression<Func<Province, bool>> exp = p => p.CountryId == country.Id;
Run Code Online (Sandbox Code Playgroud)
该表达式稍后由NHibernate Linq提供程序使用并引发异常.当我检查表达式变量exp时,我发现相等运算符的两边都转换为Int32.
{p => (Convert(p.CountryId) = Convert(value
(AddressToGo.Business.Default.AddressComponents+<>c__DisplayClass0).country.Id))}
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么两个字节值的相等运算符需要事先将这些值转换为Int32.我已经直接编写了表达式,并且让编译器为我做了.以下表达式由NHibernate Linq提供者转换得很好.
ParameterExpression prm = Expression.Parameter(typeof(Province), "p");
Expression<Func<Province, bool>> exp =
Expression.Lambda<Func<Province, bool>>
(
Expression.Equal
(
Expression.MakeMemberAccess(prm, typeof(Province).GetProperty("CountryId")),
Expression.Constant(country.Id, typeof(byte))
),
prm
);
Run Code Online (Sandbox Code Playgroud)
因此,编译器必须输出具有类型转换的表达式.有任何想法吗?
在我们的多层业务应用程序中,我们拥有ObservableCollections
从服务调用返回的自我跟踪实体.
我们的想法是希望能够从集合客户端获取实体,添加,更新和删除它们,然后将这些更改发送到服务器端,并将它们保存到数据库中.
自我跟踪实体,正如其名称所暗示的那样,可以自己跟踪其状态.当创建一个新的STE时,它具有Added状态,当你修改一个属性时,它设置Modified状态,它也可以有Deleted状态,但是当从一个ObservableCollection
(显然)中删除实体时,不会设置这个状态.如果您想要这种行为,您需要自己编写代码.
在我当前的实现中,当从中删除实体时ObservableCollection
,我将其保存在阴影集合中,这样当ObservableCollection
发送回服务器时,我可以发送已删除的项目,因此实体框架知道删除它们.
有点像:
protected IDictionary<int, IList> DeletedCollections = new Dictionary<int, IList>();
protected void SubscribeDeletionHandler<TEntity>(ObservableCollection<TEntity> collection)
{
var deletedEntities = new List<TEntity>();
DeletedCollections[collection.GetHashCode()] = deletedEntities;
collection.CollectionChanged += (o, a) =>
{
if (a.OldItems != null)
{
deletedEntities.AddRange(a.OldItems.Cast<TEntity>());
}
};
}
Run Code Online (Sandbox Code Playgroud)
现在,如果用户决定将更改保存到服务器,我可以获取已删除项目的列表,并将其发送到:
ObservableCollection<Customer> customers = MyServiceProxy.GetCustomers();
customers.RemoveAt(0);
MyServiceProxy.UpdateCustomers(customers);
Run Code Online (Sandbox Code Playgroud)
此时,UpdateCustomers
如果删除了任何项目,该方法将验证我的阴影收集,并将它们发送到服务器端.
这种方法很好,直到你开始考虑这些影子集合的生命周期.基本上,当ObservableCollection
收集垃圾时,无法知道我们需要从字典中删除阴影集合.
我提出了一些复杂的解决方案,基本上在这种情况下进行手动内存管理.我保持WeakReference
的ObservableCollection
,并每隔几秒钟我检查,看看是否引用是无效的,在这种情况下,我删除了阴影集合.
但这似乎是一个可怕的解决方案......我希望StackOverflow的集体天才可以为更好的解决方案提供帮助.
编辑:
最后我决定继承子类化ObservableCollection
.生成服务代理代码,因此更改它以返回我的派生类型是一个相对简单的任务.
感谢您的帮助!
lifecycle entity-framework observablecollection self-tracking-entities
有人可以告诉我如何在Windows Mobile下使用C#将byte []转换为ArrayList?
稍后编辑:
这就像拥有一个包含自定义类型实例的ArrayList.此列表作为字节数组转发到数据库(转换为blob)(转换由数据库API完成); 我想要的是将byte []还原为ArrayList;
.NET CF不提供BinaryFormatter;
H,
如何从C#中的.dat文件中读取前512字节的数据?我的dat文件包含二进制数据.我File.ReadAllBytes
目前正在使用从dat文件中读取数据.但是它读取所有数据,我想只读取前512个字节然后中断.我需要为这个或任何其他方法使用for循环.任何帮助表示赞赏.