public T GetOrCreateExtension()

in rd-net/RdFramework/Base/RdBindableBase.cs [250:296]


    public T GetOrCreateExtension<T>(string name, Func<T> create) where T : class =>
      GetOrCreateExtension(name, false, create);
    
    internal T GetOrCreateHighPriorityExtension<T>(string name, Func<T> create) where T : class =>
      GetOrCreateExtension(name, true, create);
    
    private T GetOrCreateExtension<T>(string name, bool highPriorityExtension, Func<T> create) where T:class
    {
      if (name == null) throw new ArgumentNullException(nameof(name));
      if (create == null) throw new ArgumentNullException(nameof(create));

      lock (myExtensions)
      {
        T res;
        if (myExtensions.TryGetValue(name, out var existing))
        {
          var val = existing.NotNull("Found null value for key: '{0}'", name) as T;
          Assertion.Require(val != null, "Found bad value for key '{0}'. Expected type: '{1}', actual:'{2}", name, typeof(T).FullName, existing.GetType().FullName);
          res = val;
        }
        else
        {
          res = create().NotNull("'Create' result must not be null");
          
          myExtensions[name] = res;
          
          if (res is IRdBindable bindable)
          {
            BindableChildren.Insert(highPriorityExtension ? 0 : BindableChildren.Count, new KeyValuePair<string, object>(name, bindable));
            var proto = TryGetProto();
            if (proto == null)
              return res;

            var bindLifetime = myBindLifetime;
            if (bindLifetime.IsAlive)
            {
              if (bindable.RdId == RdId.Nil)
                bindable.Identify(proto.Identities, RdId.Mix("." + name));
              bindable.PreBind(bindLifetime, this, name);
              bindable.Bind();
            }
          }
        }

        return res;
      }
    }