public virtual ShapeableSpecified AddMember(MemberProjection mp)
        {
            var sk = SignatureKey.Create(mp);

            _specification.Add(sk, mp);
            switch (mp.MemberType)
            {
            case MemberTypes.Property:
                object defaultValue = null;
                if (Catalog.Factory.CanResolve(SpecialFactoryContexts.Prototype, mp.ReturnType))
                {
                    defaultValue = Catalog.Factory.Resolve(SpecialFactoryContexts.Prototype, mp.ReturnType);
                }
                else
                {
                    defaultValue = Activator.CreateInstance(mp.ReturnType);
                }

                _dynamicMembers.Add(sk, defaultValue);
                break;

            case MemberTypes.Method:
                _dynamicMembers.Add(sk, mp.Implementation);

                break;
            }

            return(this);
        }
        public virtual ShapeableSpecified AddMember(MemberProjection mp, object initialValue)
        {
            var sk = SignatureKey.Create(mp);

            _specification.Add(sk, mp);
            _dynamicMembers.Add(SignatureKey.Create(mp), initialValue);
            return(this);
        }
        public virtual ShapeableSpecified AddMember(string name, object initialValue)
        {
            var sk = SignatureKey.Create(name, initialValue);

            _dynamicMembers.Add(sk, initialValue);
            _specification.Add(sk, new MemberProjection(name, initialValue));
            return(this);
        }
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var          sk     = SignatureKey.Create(binder, args);
            SignatureKey nested = null;

            if (_nestedTargets.TryGetValue(sk, out nested))
            {
                var member = _dynamicMembers[nested];
                try
                {
                    result = InvocationBinding.InvokeMember(member, binder.Name, args);
                }
                catch (RuntimeBinderException)
                {
                    result = null;
                    return(false);
                }

                return(this.WireUpForInterface(binder.Name, true, ref result));
            }

            if (_dynamicMembers.TryGetValue(sk, out result))
            {
                var functor = result as Delegate;
                if (result == null)
                {
                    return(false);
                }
                if (!binder.CallInfo.ArgumentNames.Any() && functor != null)
                {
                    try
                    {
                        result = this.InvokeMethodDelegate(functor, args);
                    }
                    catch (RuntimeBinderException)
                    {
                        return(false);
                    }
                }
                else
                {
                    try
                    {
                        result = InvocationBinding.Invoke(result,
                                                          TypeFactorization.MaybeRenameArguments(binder.CallInfo, args));
                    }
                    catch (RuntimeBinderException)
                    {
                        return(false);
                    }
                }
                return(this.WireUpForInterface(binder.Name, true, ref result));
            }
            return(this.WireUpForInterface(binder.Name, false, ref result));
        }
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            object tOldValue;

            var          sk     = SignatureKey.Create(binder);
            SignatureKey nested = null;

            if (_nestedTargets.TryGetValue(sk, out nested))
            {
                var member = _dynamicMembers[nested];
                InvocationBinding.InvokeSet(member, binder.Name, value);
            }
            else if (!_dynamicMembers.TryGetValue(sk, out tOldValue) || value != tOldValue)
            {
                _dynamicMembers[sk] = value;
            }

            return(true);
        }
        public virtual ShapeableSpecified ExposeMemberInner(string memberName, Type memberType, MemberProjection mp)
        {
            if (!_memberNames.Contains(memberName))
            {
                throw new ArgumentException(
                          string.Format("ShapeableSpecified cannot expose part of member {0}, that member doesn't exist.",
                                        memberName));
            }

            var sk = SignatureKey.Create(mp);

            switch (mp.MemberType)
            {
            case MemberTypes.Property:
            {
                var pi = memberType.GetProperty(mp.Name);
                if (null == pi)
                {
                    throw new ArgumentException(string.Format("Member {0} does not have property {1}",
                                                              memberName, mp.Name));
                }
            }
            break;

            case MemberTypes.Method:
            {
                var mi = memberType.GetMethod(mp.Name, mp.ArgumentTypes.ToArray());
                if (null == mi)
                {
                    throw new ArgumentException(string.Format("Member {0} does not have property {1}",
                                                              memberName, mp.Name));
                }
            }
            break;
            }

            _nestedTargets.Add(sk, SignatureKey.Create(memberName, memberType));
            mp.NestedName = memberName;
            _specification.Add(sk, mp);
            _memberNames.Add(memberName);

            return(this);
        }
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            var          sk     = SignatureKey.Create(binder);
            SignatureKey nested = null;

            if (_nestedTargets.TryGetValue(sk, out nested))
            {
                var member = _dynamicMembers[nested];
                result = InvocationBinding.InvokeGet(member, binder.Name);
                return(this.WireUpForInterface(binder.Name, true, ref result));
            }

            if (_dynamicMembers.TryGetValue(sk, out result))
            {
                return(this.WireUpForInterface(binder.Name, true, ref result));
            }

            result = null;
            return(this.WireUpForInterface(binder.Name, false, ref result));
        }
        public virtual ShapeableSpecified AddMember(string name, Type type, string protoTypeFactoryContext = null)
        {
            if (String.IsNullOrEmpty(protoTypeFactoryContext))
            {
                protoTypeFactoryContext = SpecialFactoryContexts.Prototype.ToString();
            }

            var    sk = SignatureKey.Create(name, type);
            object instancePrototype = null;

            if (Catalog.Factory.CanResolve(protoTypeFactoryContext, type))
            {
                instancePrototype = Catalog.Factory.Resolve(protoTypeFactoryContext, type);
            }
            else
            {
                instancePrototype = Activator.CreateInstance(type);
            }

            _dynamicMembers.Add(sk, instancePrototype);
            _specification.Add(sk, new MemberProjection(name, type));
            return(this);
        }