/// <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; } }
/// <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 } }