Как сказать, когда инициализатор объекта сделан - PullRequest
0 голосов
/ 09 февраля 2012

У меня есть различные производные объекты, с которыми я бы хотел, чтобы пользователь мог использовать инициализаторы объектов.У меня есть свойство «Initializing», которое я хочу иметь значение true, так как эти поля устанавливаются, а затем я хочу, чтобы свойство Initializing впоследствии было установлено в значение false.

Как определить, когда инициализатор объекта выполняется длябыть в состоянии сделать это?

class Foo
{    
    Public Foo(string p1, string p2)
    {
        Initializing = true;
        Property1 = p1;
        Property2 = p2;
        Initializing = false;
    }

    bool Initializing;

    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        if(Initializing) return; // Don't want to continue if initializing
        // Do something here
    }
}

В приведенном выше примере это работает нормально, если вы используете конструктор.Однако проблема заключается в том, чтобы заставить его работать так же, как с инициализатором объекта.

РЕДАКТИРОВАТЬ: Для всех вас, скептиков, вот кто-то еще ищет именно то, что я ищу - http://blogs.clariusconsulting.net/kzu/how-to-make-object-initializers-more-useful/

К сожалению, похоже, что это невозможно.

Ответы [ 6 ]

4 голосов
/ 09 февраля 2012

Если вам действительно нужно отслеживать инициализацию вашего объекта, вам нужно реализовать эту логику вручную.Одним из подходов является копирование того, что используется генератором кода WinForms.Где объекты предоставляют интерфейс ISupportInitialize , когда они хотят обновить свойства в пакете.Таким образом, использование будет что-то вроде ...

var x = new Foo();
x.BeginInit();
x.Property1 = 1;
x.Property2 = 2;
x.EndInit();
3 голосов
/ 09 февраля 2012

Нет смысла устанавливать какой-либо флаг. Вы не можете получить доступ к объекту до тех пор, пока не запустятся инициализаторы. Например:

var object = new object() { Prop1 = "Boo" }

Поскольку ссылка, возвращаемая из new, не может быть доступна до тех пор, пока не будет установлен Prop1, нет никакого способа получить доступ к какому-либо из свойств, поэтому нет необходимости контролировать доступ или беспокоиться о том, выполнено это или нет ". *

Хотя, я полагаю, я вижу, как у вас может быть что-то вроде этого:

public class Foo {
    private int _value;
    public int Bar {
        set {
            _value = value * Baz; // don't want to do this if initializing
        }
    }

    public int Baz { get; set; }
}

Если это то, что вас беспокоит, значит, вы неправильно проектируете свои объекты. Свойства не должны побочные эффекты, как это. Невозможно узнать, была ли выполнена вся инициализация.

1 голос
/ 09 февраля 2012

Вместо того, чтобы полагаться на явное свойство, сообщающее вам, когда инициализируется ваш объект, вы можете использовать метод DoSomething для проверки того, что он обладает информацией, необходимой для его работы. Ваш пример довольно грубый, и я ожидаю, что ваша реальная реализация более сложна, поэтому я просто предположу, что Property1 и Property2 должны быть присвоены что-то (то есть просто не пустая строка перед продолжением) :

class Foo
{    
    public Foo(string p1, string p2)
    {
        Property1 = p1;
        Property2 = p2;
    }

    string Property1 { get; set; } 
    string Property2 { get; set; }

    public void DoSomething()
    {
        // *** Replace this with something valid to your real code
        if(!string.IsNullOrEmpty(Property1) || !string.IsNullOrEmpty(Property2)) 
            return; // Don't want to continue if not initialized
        // Do something here
    }
}

UPDATE

Не имея представления об объектной модели, с которой вы на самом деле работаете, вот возможная альтернатива, основанная на модели, широко используемой в рамках фреймворка:

class Foo
{
    public void DoSomething(FooConfig config)
    {
    }
}

OR

class Foo
{
    private FooConfig config_;

    public Foo(FooConfig config)
    {
        config_ = config;
    }

    public void DoSomething()
    {
    }
}

Где FooConfig определяется:

class FooConfig
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

И DoSomething вызывается с помощью:

(new Foo()).DoSomething(new FooConfig() { Property1 = "abc"; Property2 = "def"; });

OR

(new Foo(new FooConfig() { Property1 = "abc"; Property2 = "def"; })).DoSomething();

Это можно легко изменить, чтобы приспособить использование конструктора к Foo или FooConfig.

1 голос
/ 09 февраля 2012

Поскольку инициализация объекта является просто синтаксическим сахаром, вы не можете отличить его от обычных наборов свойств. Также я не могу придумать разумного случая, когда вы хотите относиться к ним по-другому.

Тем не менее, если вы говорите, что должно быть установлено как минимум 1 из x свойств (будь то сокращенный или сокращенный синтаксис), тогда вы можете установить для инициализации значение true в ctor, а затем установить значение false для каждого набора свойств.

1 голос
/ 09 февраля 2012

Этот вопрос не имеет смысла.Синтаксис инициализатора объекта является просто синтаксическим сахарным сокращением.

Это:

var myInstance = new someClass()
{
    Prop1 = "",
    Prop2 = "",
    Prop3 = "",
    Prop4 = "",
    Prop5 = ""
}

Точно так же, как это:

var myInstance = new someClass();
myInstance.Prop1 = "";
myInstance.Prop2 = "";
myInstance.Prop3 = "";
myInstance.Prop4 = "";
myInstance.Prop5 = "";

Там нет "Готово »будет обнаружено.

То, что вы хотите сделать, можно сделать примерно так:

class someClass()
{
  public string AStringProperty { get; set; }
  public bool IsInitiazlied 
  {
    return string.IsNullOrWhitespace(this.AStringProperty);
  }
}

Или, заставьте ctor принять начальное состояние значений, затем вашгарантируется настройка.

class someClass()
{
  public string AStringProperty { get; set; }
  public someClass(string AStringPropertyInit)
  {
      this.AStringProperty = AStringPropertyInit;
  }
}

РЕДАКТИРОВАТЬ

class Foo
{    
    Public Foo(string p1, string p2)
    {

        _property1= p1; //set the backing store directly, 
                        //skips the side effect in the setter
        Property2 = p2;

        DoSomething(); // now cause the side effect
                       // we know everything is setup
    }



    string _property1;
    string Property1 
    {
        get { return _property1; } 
        set { _property1 = value; DoSomething(); }
    }

    string Property2 { get; set; }

    public void DoSomething()
    {
        // Do something here
    }
}
0 голосов
/ 09 февраля 2012

Объектный инициализатор - это всего лишь сокращение для создания объекта и установки для него набора свойств.Не имеет смысла спрашивать «когда оно завершится».

Если вы хотите, чтобы состояние вашего объекта зависело от определенного набора инициализируемых свойств, вы можете добавить код в установщик для каждогособственности и отслеживать его внутри.Однако это действительно зависит от того, чего вы пытаетесь достичь.

Обновление

Просто читайте ваши комментарии к ответу @ asawyer.Нет никакого способа узнать, устанавливается ли свойство в инициализаторе или нет.Просто чтобы проиллюстрировать - вот три фрагмента кода, которые делают одно и то же, за исключением того, что вы, кажется, хотите, чтобы для каждого из них было поведение по-разному.установщики свойств, и запускают некоторый побочный эффект для всех, кроме первого выполнения, но сказать, что я хочу запускать побочный эффект, только если клиент изменяет начальную конфигурацию объекта, не имеет смысла после завершения ctor.

...