Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.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# - Fatal编程技术网

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