我试图找出改变现有实施工厂的最佳方法,以便将我的信号器集线器中的事件动态注册到我的通用服务。
最初我打算将集线器注入服务,但我不想将它们连接起来或让客户端必须实现自己的集线器等,所以我决定创建一个订阅活动
但我不希望客户注册他们自己的工厂我想采用所有现有的工厂,并根据配置选项进行统一注册:
我有一个通用的crud服务,简化版看起来像这样
public interface IAsyncCRUDService<TDTO>
{
Task<TDTO> Get(object[] id);
Task<TDTO[]> GetList(IFilterResolver queryOptions);
Task<TDTO> Create(TDTO skillDTO);
Task<TDTO> Update(object[] id, TDTO skillDTO);
Task<bool> Delete(object[] id);
event EventHandler<TDTO> OnCreate;
event EventHandler<TDTO> OnUpdate;
}
我试图想办法让配置使用自动将我的集线器事件注册到我的服务。
public interface ICRUDServiceHubBase<in T>
{
Task Create(T entityDTO);
Task Update(T entityDTO);
Task Delete(object[] id);
}
在我的创业中,我想自动注册服务的事件。我希望这很容易和可配置
//TODO: Move to extensions
protected List<ServiceDescriptor> GetGenericServicesFromGenericTypeDefinition(IServiceCollection services, Type baseGenericTypeDefinition)
{
if(false == baseGenericTypeDefinition.IsGenericTypeDefinition)
{
throw new Exception($"Invalid Argument {nameof(baseGenericTypeDefinition)}");
}
return services.Where(s => s.ImplementationType.GetTypeInfo().IsGenericType)
.Where(s => s.ImplementationType.GetTypeInfo().GetGenericTypeDefinition() == baseGenericTypeDefinition).ToList()
}
public EventHandler<TDTO> RegisterHubsCreate<TDTO>(IAsyncCRUDService<TDTO> service, ICRUDServiceHubBase<TDTO> hubService)
{
EventHandler<TDTO> handlerRef = (object obj, TDTO args) => { hubService.Create(args); };
service.OnCreate += handlerRef;
return handlerRef;
}
public void RegisterHubsEvents(IServiceCollection services)
{
var crudServiceDescriptors = this.GetGenericServicesFromGenericTypeDefinition(services, typeof(IAsyncCRUDService<>));
foreach (var serviceDescriptor in crudServiceDescriptors)
{
var originalFunc = serviceDescriptor.ImplementationFactory;
Func<IServiceProvider, object> HubsRegistered = (IServiceProvider provider) => {
var serviceObj = originalFunc(provider);
//TODO: since this is an instance you probably need to grab the interface type first
//or you'll risk grrabbing the wrong parameter
var dtoType = serviceObj.GetType().GetGenericArguments().First();
var hubType = typeof(ICRUDServiceHubBase<>).MakeGenericType(dtoType);
//Is this risky if the hub is transient will my object be disposed before the event fires?
var hub = provider.GetService(hubType);
var registerHubsDynamically = this.GetType().GetMethod("RegisterHubsCreate").MakeGenericMethod(dtoType);
registerHubsDynamically.Invoke(this, new object[] { serviceObj, hub });
return serviceObj;
};
serviceDescriptor.ImplementationFactory = HubsRegistered;
}
}
如何动态发送实现工厂,或者某些事件如何在调用实现工厂时注册?