C# 完全初始化类

C# 完全初始化类,c#,constructor,initialization,C#,Constructor,Initialization,我在类中使用initiazling属性 我想在完全初始化后运行一个验证方法。 我不能使用构造函数,原因很明显。有没有一种方法可以在类初始化事件中实现这一点 var t = new Foo { foo = ""; } class Foo { public string foo {get; set;} ... public bool validate {get ; set;} priv

我在类中使用initiazling属性 我想在完全初始化后运行一个验证方法。 我不能使用构造函数,原因很明显。有没有一种方法可以在类初始化事件中实现这一点

var t = new Foo
              {
                foo = "";
              }

class Foo
{
   public string foo {get; set;}
   ...
   public bool validate {get ; set;}

   private void validation()
  {
     if(foo == "")
        validate = false;
     if ...
   }

}

一种方法是为验证目的而设计的接口<例如,代码>IValidation<代码>验证然后可以包含一个
验证
方法。需要提供行为的类现在可以以可管理的方式提供行为

这可以防止构造函数中的膨胀,因为IMHO是糟糕的设计。

(注意:为了清楚起见,我将属性重命名为Bar,以便轻松将其与Foo类型区分开来)

如果
属性在构造时必须有效,为什么不在构造函数中要求它?为什么允许构造无效对象

class Foo
{
    public Foo(string bar) {
        if(!IsValidBar(bar))
            throw new ArgumentException("bar is not valid.", "bar");
        this.Bar = bar;
    }
    public string Bar {get; set;}

    private bool IsValidBar(string bar)
    {
        // blah blah
    }
}
或者,如果您可以在不使用
Bar
属性值的情况下构造
Foo
的实例,但不允许将
Bar
设置为无效值,则可以在setter中验证这一点:

class Foo
{
    private string bar;
    public string Bar
    {
        get { return bar; }
        set
        {
            if(!IsValidBar(value))
                throw new ArgumentException("bar is not valid.", "value");
            bar = value;
        }
    }

    private bool IsValidBar(string bar)
    {
        // blah blah
    }
}

您可以避免使用属性初始值设定项,只需将所有代码移动到构造函数中,如果有很多属性,则使用可选参数。这样,您将获得某种属性初始值设定项构造函数,但在初始化完成后仍然能够验证该类。大概是这样的:

class Foo 
{    
   public string Foo {get; set;} 
   public string Bar {get; set;} 
   public bool IsValid {get ; set;}

   private void Validation()   
   {      
      if(foo == "")         
       IsValid = false;      
     if ...    
   }  

   public void Foo(string foo = string.Empty, string bar = string.Empty)
   {
      Foo = foo;
      Bar = bar;
      Validation();
   }
} 

.....

var t = new Foo (Foo = "SomeString");
public bool IsValid
{
  get 
  { 
    if (!isValidated)
       Validation();
    return isValid;
  }
  private set { isValid = value; }
}

public string Foo
{
  get { return foo; }
  set 
  {
    foo = value;         
    isValidated := false;
  }
}
缺点是这是一种相对较新的C#4语法

如果不能使用c#4,可以使用属性访问器启用验证,例如:

public string Foo
{
  get { return foo; }
  set 
  {
    foo = value;         
    Validation();
  }
}
但是,这将评估每个集合的有效性,如果同时设置许多属性,可能会很慢。您还可以将
get
访问器与一些延迟加载结合使用,如下所示:

class Foo 
{    
   public string Foo {get; set;} 
   public string Bar {get; set;} 
   public bool IsValid {get ; set;}

   private void Validation()   
   {      
      if(foo == "")         
       IsValid = false;      
     if ...    
   }  

   public void Foo(string foo = string.Empty, string bar = string.Empty)
   {
      Foo = foo;
      Bar = bar;
      Validation();
   }
} 

.....

var t = new Foo (Foo = "SomeString");
public bool IsValid
{
  get 
  { 
    if (!isValidated)
       Validation();
    return isValid;
  }
  private set { isValid = value; }
}

public string Foo
{
  get { return foo; }
  set 
  {
    foo = value;         
    isValidated := false;
  }
}

您可以向属性添加验证逻辑。验证类是否在分配属性后初始化,并在初始化完成时引发静态事件。您可以通过将事件发送器强制转换为Foo来获取对实例的引用

public string Foo 
{ get { return _foo; }
  set
  {
     _foo = value;
     if (IsInitialized)
       OnClassInitialized();
  }
} 

public static event EventHandler ClassInitialized;

private OnClassInitialized()
{
   if (ClassInitialized != null)
      ClassInitialized(this, EventArgs.Empty);
} 
用法:

Foo.ClassInitialized += (sender, e) => 
{ 
  Foo foo = sender as Foo;  
  ...
};

您可以使用面向方面的编程,如postsharp。但是你会失去性能。

我认为构造函数被调用了,尽管你不想我不知道你不能在构造函数中这样做的明显原因。你能澄清一下吗?我想这是因为属性初始值设定者…是的,这是因为属性初始值设定者…伙计们。这是一个复杂的问题,甚至是更复杂的答案。我不想使用构造函数,因为初始化器是更漂亮的代码。也许这是值得考虑的。我可能会使用C'tor和参数。谢谢