Beispiel #1
0
        /// <summary>
        /// Resource listener
        /// </summary>
        public MdmResourceHandler()
        {
            // Register the master
            this.m_dataManager       = MdmDataManagerFactory.GetDataManager <TModel>();
            this.m_policyEnforcement = ApplicationServiceContext.Current.GetService <IPolicyEnforcementService>();
            this.m_batchRepository   = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Bundle> >();
            this.m_adhocCache        = ApplicationServiceContext.Current.GetService <IAdhocCacheService>();

            // Validate the match configuration exists
            var matchConfigService = ApplicationServiceContext.Current.GetService <IRecordMatchingConfigurationService>();

            this.m_notifyRepository = ApplicationServiceContext.Current.GetService <IRepositoryService <TModel> >() as INotifyRepositoryService <TModel>;
            if (this.m_notifyRepository == null)
            {
                throw new InvalidOperationException($"Could not find repository service for {typeof(TModel)}");
            }

            this.m_classConceptKey = typeof(TModel).GetCustomAttributes <ClassConceptKeyAttribute>(false).Select(o => Guid.Parse(o.ClassConcept)).ToArray();

            // Subscribe
            this.m_notifyRepository.Inserting  += this.OnPrePersistenceValidate;
            this.m_notifyRepository.Saving     += this.OnPrePersistenceValidate;
            this.m_notifyRepository.Obsoleting += this.OnPrePersistenceValidate;
            this.m_notifyRepository.Inserting  += this.OnInserting;
            this.m_notifyRepository.Saving     += this.OnSaving;
            this.m_notifyRepository.Obsoleting += this.OnObsoleting;
            this.m_notifyRepository.Retrieved  += this.OnRetrieved;
            this.m_notifyRepository.Retrieving += this.OnRetrieving;
            this.m_notifyRepository.Querying   += this.OnQuerying;

            // Bind down the repository services
            // TODO: Determine if this level of interception is required - this only impacts when (for example) IRepositoryService<Patient>
            // is bound to MDM and someone calls IRepositoryService<Person> - without it calls to the former will return MDM based resources
            // whereas calls to the latter will return raw non-MDM resources (even if they are patients - they will be local, non-MDM patients).
            var baseType = typeof(TModel).BaseType;

            while (typeof(Entity).IsAssignableFrom(baseType) || typeof(Act).IsAssignableFrom(baseType))
            {
                var repoType     = typeof(INotifyRepositoryService <>).MakeGenericType(baseType);
                var repoInstance = ApplicationServiceContext.Current.GetService(repoType);
                if (repoInstance == null)
                {
                    break;
                }

                // Hand off reflection notifcation
                var eventHandler    = repoType.GetEvent("Queried");
                var parmType        = typeof(QueryResultEventArgs <>).MakeGenericType(baseType);
                var parameter       = Expression.Parameter(parmType);
                var dataAccess      = Expression.MakeMemberAccess(parameter, parmType.GetProperty("Results"));
                var principalAccess = Expression.MakeMemberAccess(parameter, parmType.GetProperty("Principal"));
                var methodInfo      = this.GetType().GetGenericMethod(nameof(OnGenericQueried), new Type[] { baseType }, new Type[] { typeof(IEnumerable <>).MakeGenericType(baseType), typeof(IPrincipal) });
                var lambdaMethod    = typeof(Expression).GetGenericMethod(nameof(Expression.Lambda), new Type[] { eventHandler.EventHandlerType }, new Type[] { typeof(Expression), typeof(ParameterExpression[]) });
                var lambdaAccess    = lambdaMethod.Invoke(null, new object[] { Expression.Assign(dataAccess, Expression.Call(Expression.Constant(this), (MethodInfo)methodInfo, dataAccess, principalAccess)), new ParameterExpression[] { Expression.Parameter(typeof(Object)), parameter } }) as LambdaExpression;
                eventHandler.AddEventHandler(repoInstance, lambdaAccess.Compile());
                //var lamdaAccess = Expression.Lambda(Expression.Call(Expression.Constant(this), this.GetType().GetMethod(nameof(OnGenericQueried))), dataAccess), Expression.Parameter(typeof(Object)), parameter);
                // Continue down base types
                baseType = baseType.BaseType;
            }
        }
Beispiel #2
0
 /// <summary>
 /// Creates a new entity merger service
 /// </summary>
 public MdmEntityMerger(IDataPersistenceService <Bundle> batchService, IThreadPoolService threadPool, IPolicyEnforcementService policyEnforcement, IStoredQueryDataPersistenceService <TEntity> persistenceService, IFastQueryDataPersistenceService <EntityRelationship> relationshipPersistence)
 {
     this.m_dataManager             = MdmDataManagerFactory.GetDataManager <TEntity>();
     this.m_batchPersistence        = batchService;
     this.m_pepService              = policyEnforcement;
     this.m_entityPersistence       = persistenceService;
     this.m_relationshipPersistence = relationshipPersistence;
     this.m_threadPool              = threadPool;
     if (this.m_relationshipPersistence is IReportProgressChanged irpc)
     {
         irpc.ProgressChanged += (o, e) => this.ProgressChanged?.Invoke(o, e); // pass through progress reports
     }
 }