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);
        }
        private IEnumerable <Aspect> Find(
            string name,
            Type returnType,
            MemberTypes kind,
            int argCount,
            IEnumerable <string> argumentNames,
            Aspect.InterceptMode mode)
        {
            if (!_mappings.ContainsKey(name))
            {
                return(null);
            }

            var lt = _mappings[name];
            var mp = lt.Keys
                     .FirstOrDefault(
                p => p.ReturnType == returnType &&
                p.MemberType == kind &&
                p.ArgumentCount == argCount &&
                p.GetArgumentNamesHashCode() == MemberProjection.HashArgumentNames(argumentNames));

            if (mp == null)
            {
                return(Enumerable.Empty <Aspect>());
            }

            var aspects = (from a in lt[mp].SelectMany(ap => ap.ProvideAspects(mode))
                           orderby _aspectCategoryOrdering[a.Category.EnumName()]
                           select a).Distinct();

            return(aspects);
        }
        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 static SignatureKey Create(MemberProjection projection)
        {
            switch (projection.MemberType)
            {
            case MemberTypes.Property:
                return(new SignatureKey(EnumerableEx.OfThree(
                                            MemberTypes.Property.GetHashCode(), projection.Name.GetHashCode(),
                                            projection.ReturnType.GetHashCode())));

                break;

            case MemberTypes.Method:
                return(new SignatureKey(EnumerableEx.OfThree(
                                            MemberTypes.Method.GetHashCode(),
                                            projection.Name.GetHashCode(),
                                            projection.ArgumentCount
                                            ).Concat(projection.ArgumentTypes.Select(at => at.GetHashCode()))));

                break;

            default:
                return(null);
            }
        }
        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);
        }