C#延迟属性设置
我正在做一个项目,在那里我需要排队等候一些财产的变化。假设我有:C#延迟属性设置,c#,C#,我正在做一个项目,在那里我需要排队等候一些财产的变化。假设我有: public class foo { string bar { get; set; } int bar1 { get; set } } 我希望有一些代码如下所示: //Store value set actions in a queue foo.SetValue(bar, "abc"); foo.SetValue(bar1, 123); //Preview changes foreach(Item change i
public class foo
{
string bar { get; set; }
int bar1 { get; set }
}
我希望有一些代码如下所示:
//Store value set actions in a queue
foo.SetValue(bar, "abc");
foo.SetValue(bar1, 123);
//Preview changes
foreach(Item change in foo.ChangeQueue)
{
Console.Write(change.PropertyName.ToString());
Console.Write(change.Value.ToString());
}
//Apply actions
foo.CommitChanges();
实现这一点的最佳方法是什么?您可以使用
字典
作为ChangeQueue来存储您的值
您可以迭代为
foreach(KeyValuePair<string,object> item in ChangeQueue){
Console.WriteLine(item.Key);// name of property
Console.WriteLine(item.Value); // value of property
}
public void SetValue(string name, object value){
PropertyInfo p = this.GetType().GetProperty(name);
// following convert and raise an exception to preserve type safety
ChangeQueue[name] = Convert.ChangeType(value,p.PropertyType);
}
public void ApplyChanges(){
foreach(KeyValuePair<string,object> item in ChangeQueue){
PropertyInfo p = this.GetType().GetProperty(item.Key);
p.SetValue(this, item.Value, null);
}
}
foreach(ChangeQueue中的KeyValuePair项){
Console.WriteLine(item.Key);//属性名称
Console.WriteLine(item.Value);//属性的值
}
public void SetValue(字符串名称、对象值){
PropertyInfo p=this.GetType().GetProperty(名称);
//以下命令转换并引发异常以保持类型安全
ChangeQueue[name]=Convert.ChangeType(值,p.PropertyType);
}
公共无效应用程序更改(){
foreach(ChangeQueue中的KeyValuePair项){
PropertyInfo p=this.GetType().GetProperty(item.Key);
p、 SetValue(此项,item.Value,null);
}
}
使用回调的“类型安全”版本。这不会自动删除重复的设置。它也不使用反射,因此属性名错误将在编译时失败。该方法可以扩展为需要一个“名称”,并通过使用字典支持(根据Akash的回答)删除重复项,或者允许“setter”返回一个值(例如成功或失败或旧值,等等)
接口设置器{
无效应用();
}
类设置器:设置器{
公共数据;
公共行动组fn;
公开无效申请(){
SetFn(数据);
}
}
List changeQueue=新列表();
无效设置值(动作设置fn,T数据){
添加(新的设置程序){
数据=数据,
SetFn=SetFn,
});
}
作废ApplyChanges(){
foreach(changeQueue中的变量s){
s、 应用();
}
}
// .. 后来
SetValue(x=>System.Console.WriteLine(x),“你好,世界!”);
ApplyChanges();
此方法也可以在被监视对象的“外部”使用,因为所有操作都在潜在的闭包中
愉快的编码。所以您只关心最新的设置,还是需要将对特定属性的所有更改排队?如果需要跟踪所有更改或更改顺序,则几乎可以直接替换上面的字典。
IEnumerable
。这看起来还可以。但是,没有类型安全性。您能详细说明一下:SetValue(x=>System.Console.WriteLine(x),“hello world!”)?我不能马上让它工作,我一定是遗漏了什么。SetValue
(实际上是命名错误的)--它会在以后执行一个操作(当调用ApplyChanges时)。在这种情况下,我只是在写控制台时产生副作用--这可能是一个真实的例子:SetValue(x=>myObject.IntProperty=x,10)
(注意,它捕获了将在闭包中设置值的目标对象。x
的类型是传入的值的类型(我的代码中的字符串,注释中的示例中的int),并且是从方法定义中的T
推断出来的(两个T必须相同,所以C#努力使其匹配)@Matt如果此方法是类的一部分,也可以以类型安全的方式将当前类传递给操作(向Setter添加第二个类型参数),例如,通过一些重新处理:myObject.SetValue((x,o)=>o.Property=x,…)
,从而避免闭包(其中o是myObject,但名称不同)。
interface Setter {
void Apply();
}
class Setter<T> : Setter {
public T Data;
public Action<T> SetFn;
public void Apply() {
SetFn(Data);
}
}
List<Setter> changeQueue = new List<Setter>();
void SetValue<T>(Action<T> setFn, T data){
changeQueue.Add(new Setter<T> {
Data = data,
SetFn = setFn,
});
}
void ApplyChanges(){
foreach (var s in changeQueue){
s.Apply();
}
}
// .. later on
SetValue(x => System.Console.WriteLine(x), "hello world!");
ApplyChanges();