private static void BuildIdAccess(Type entityType,
                                              ref MetadataStorage metadataStorage,
                                              out Func <object, string> idGetAccessor,
                                              out Action <object, string> idSetAccessor)
            {
                var idMember = GetIdMember(entityType);

                if (idMember == null)
                {
                    var ms = metadataStorage = metadataStorage ?? new MetadataStorage();

                    string GetIdFromMetadata(object entity)
                    {
                        return(ms.GetMetadata(entity).GetId());
                    }

                    void SetIdToMetadata(object entity, string id)
                    {
                        ms.GetMetadata(entity).SetId(id);
                    }

                    idGetAccessor = GetIdFromMetadata;
                    idSetAccessor = SetIdToMetadata;
                    return;
                }

                // We could theoretically allow setting id to an entity,
                // but this will need support for transforming a stringified id back to its original representation.
                idSetAccessor = null;

                var idType          = DataPropertyHelper.GetIdType(entityType);
                var entityParameter = Expression.Parameter(typeof(object), "entity");
                var convertedEntity = Expression.Convert(entityParameter, entityType);

                var idAccess = default(Expression);

                if (idMember.MemberType == MemberTypes.Method)
                {
                    idAccess = Expression.Call(convertedEntity, (MethodInfo)idMember);
                }
                else if (idMember.MemberType == MemberTypes.Field || idMember.MemberType == MemberTypes.Property)
                {
                    idAccess = Expression.MakeMemberAccess(convertedEntity, idMember);
                }

                var toStringMethod = idType.GetMethod(nameof(ToString), BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, Type.EmptyTypes, null);

                Assert(toStringMethod != null);

                if (idAccess != null)
                {
                    var toStringCall = Expression.Call(idAccess, toStringMethod);
                    idGetAccessor = Expression.Lambda <Func <object, string> >(toStringCall, entityParameter).Compile();
                }
                else
                {
                    idGetAccessor = null;
                }
            }
예제 #2
0
        private IInMemoryDatabase <TData> CreateTypedStore <TData>()
            where TData : class
        {
            var dataType = typeof(TData);
            var idType   = DataPropertyHelper.GetIdType <TData>();

            if (idType == null)
            {
                throw new Exception($"Cannot store objects of type '{typeof(TData).FullName}'. An id cannot be extracted."); // TODO
            }


            var typedStore = Activator.CreateInstance(typeof(InMemoryDatabase <,>).MakeGenericType(idType, dataType));

            return((IInMemoryDatabase <TData>)typedStore);
        }