Методы расширения и динамика не очень хорошо сочетаются. Кроме того, строки «Propertyname» являются бельмом на глазу.

меет смыслНулевой условный оператор, Хорошо объяснил вэтот ответ слишком.

Мне было интересно, можно ли сделать подобную проверку, как это, когда мой объект является объектом динамического / расширения. Позвольте мне показать вам некоторый код:

Учитывая эту иерархию классов

public class ClsLevel1
{
    public ClsLevel2 ClsLevel2 { get; set; }
    public ClsLevel1()
    {
        this.ClsLevel2 = new ClsLevel2(); // You can comment this line to test
    }        
}

public class ClsLevel2
{
    public ClsLevel3 ClsLevel3 { get; set; }
    public ClsLevel2()
    {
        this.ClsLevel3 = new ClsLevel3();
    }       
}

public class ClsLevel3
{
    // No child
    public ClsLevel3()
    {
    }
}

Если я выполняю этот вид цепной проверки нуля, это работает

ClsLevel1 levelRoot = new ClsLevel1();
if (levelRoot?.ClsLevel2?.ClsLevel3 != null)
{
     // will enter here if you DO NOT comment the content of the ClsLevel1 constructor
}
else
{
     // will enter here if you COMMENT the content of the ClsLevel1 
}

Теперь я попытаюсь воспроизвести это поведение с помощью динамики (ExpandoObjects).

dynamic dinRoot = new ExpandoObject();
dynamic DinLevel1 = new ExpandoObject();
dynamic DinLevel2 = new ExpandoObject();
dynamic DinLevel3 = new ExpandoObject();

dinRoot.DinLevel1 = DinLevel1;
dinRoot.DinLevel1.DinLevel2 = DinLevel2;
//dinRoot.DinLevel1.DinLevel2.DinLevel3 = DinLevel3; // You can comment this line to test

if (dinRoot?.DinLevel1?.DinLevel2?.DinLevel3 != null)
{
     // Obviously it will raise an exception because the DinLevel3 does not exists, it is commented right now.
}

Есть ли способ симулировать это поведение с динамикой? Я имею в виду, проверить на ноль в длинной цепочке членов?

 taquion17 окт. 2017 г., 15:51
Если нет пути, то мы должны его построить.
 Evk17 окт. 2017 г., 15:06
Насколько я знаю - нет способа сделать это.
 Ewerton17 окт. 2017 г., 17:45
@mjwills в моем случаеdoes this property exists а такжеnull check это то же самое
 mjwills17 окт. 2017 г., 14:58
Итак, вы хотитеdoes this property exist проверить, а неnull проверить?

Ответы на вопрос(2)

Решение Вопроса

вы можете унаследовать от DynamicObject и предоставить собственную реализацию:

class MyExpando : DynamicObject
    {
        private readonly Dictionary<string, object> _dictionary = new Dictionary<string, object>();

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            var name = binder.Name.ToLower();
            result = _dictionary.ContainsKey(name) ? _dictionary[name] : null;
            return true;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            _dictionary[binder.Name.ToLower()] = value;
            return true;
        }
    }

Тестирование:

 private static void Main(string[] args)
        {
            dynamic foo = new MyExpando();
            if (foo.Boo?.Lol ?? true)
            {
                Console.WriteLine("It works!");
            }
            Console.ReadLine();
        }

Выход будет "Это работает!" Поскольку Boo не существует, мы получаем нулевую ссылку, чтобы мог работать нулевой условный оператор.

Что мы делаем здесь, чтобы вернутьзначение NULL ссылка на выходной параметрTryGetMember каждый раз, когда свойство не найдено, и мы всегда возвращаем true.

 taquion17 окт. 2017 г., 18:29
Рад это знать! \ м / м
 Ewerton08 нояб. 2017 г., 14:13
Есть ли способ заставить MyExpando действовать как динамический по умолчанию, я имею в виду: dynamic d = new ExpandoObject (); d.SomeProp = "foo"; // работает CustomDynamic c = new CustomDynamic (); c.SomeProp = "bar"; // Не работает
 Ewerton17 окт. 2017 г., 18:20
Благодаря @taquion, я сделал несколько тестов, таких как: 1) сделать последнее растяжение пустым или не нулевым, 2) сделать последний объект свойством нулевым или ненулевым, 3) сделать средним расширением пустым или не нулевым, так далеко все работало нормально

исправлено, поскольку ExpandoObjects и методы расширения не работают вместе. Чуть менее приятный, но, надеюсь, еще пригодный для использования.

Вспомогательный метод (ы):

public static class DynamicExtensions
{
    public static Object TryGetProperty(ExpandoObject obj, String name)
    {
        return name.Split('.')
                   .Aggregate((Object)obj, (o, s) => o != null
                                                      ? TryGetPropertyInternal(o, s)
                                                      : null);
    }

    private static Object TryGetPropertyInternal(Object obj, String name)
    {
        var dict = obj as IDictionary<String, Object>;
        return (dict?.ContainsKey(name) ?? false) ? dict[name] : null;
    }
}

Использование:

if (DynamicExtensions.TryGetProperty(dinRoot, "DinLevel1.DinLevel2.DinLevel3") != null)
 decPL17 окт. 2017 г., 15:29
В среде, не поддерживающей методы расширения; каким-то образом, хотя это будет работать. Обновляю мой ответ сейчас.
 Henk Holterman17 окт. 2017 г., 15:19
Вы проверяли это? Я не думаю, что цепочка будет работать.
 Henk Holterman17 окт. 2017 г., 15:36
Методы расширения и динамика не очень хорошо сочетаются. Кроме того, строки «Propertyname» являются бельмом на глазу.

Ваш ответ на вопрос