我正在实现一种工厂模式,并在Code Review上找到了this neat-looking pattern。
我用以下一些变体实现了该解决方案:
我有一个工厂类,看起来像这样:
public class SearchableServiceFactory<TSearchableLookupService, TOutputDto>
where TOutputDto : IBaseOutputDto
where TSearchableLookupService : ISearchableLookupService<TOutputDto>
{
static readonly Dictionary<string, Func<TSearchableLookupService>> _SearchableLookupServicesRegistry =
new Dictionary<string, Func<TSearchableLookupService>>();
private SearchableServiceFactory() { }
public static TSearchableLookupService Create(string key)
{
if (_SearchableLookupServicesRegistry.TryGetValue(
key, out Func<TSearchableLookupService> searchableServiceConstructor)
)
return searchableServiceConstructor();
throw new NotImplementedException();
}
public static void Register<TDerivedSearchableService>
(
string key,
Func<TSearchableLookupService> searchableServiceConstructor
)
where TDerivedSearchableService : TSearchableLookupService
{
var serviceType = typeof(TDerivedSearchableService);
if (serviceType.IsInterface || serviceType.IsAbstract)
throw new NotImplementedException();
_SearchableLookupServicesRegistry.Add(key, searchableServiceConstructor);
}
这样可行。我从代码中调用它,因此:
...
SearchableServiceFactory<OrgLookupService, OrgOutputDto>.Register<OrgLookupService>
(
nameof(Organization), () => new OrgLookupService(_Context, _OrganizationRepository)
);
...
这样可行。构造函数与键一起添加到字典中。然后,我通过键来检索该构造函数,以获取一个实例并对其进行处理,如下所示:
SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>.Create(myKey).DoAThing();
失败是因为字典中不存在这样的值。因为它是静态的,所以注册和创建所需实例的类中的方法也是如此。
如果这很重要,我正在使用.NET Core 2.1(这似乎是严格的C#问题)。
最佳答案
SearchableServiceFactory<OrgLookupService, OrgOutputDto>
与SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>
类型不同,因此,即使静态属性也不同。
在编译器看来,它们是不同的类型。仅仅因为OrglookupService
是ISearchableLookupService
,并不是每个ISearchableLookupService
都是OrglookupService
。
可能的解决方法是使用SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>
注册您的对象,但这将要求ISearchableLookupService
是协变的。
public interface ISearchableLookupService<out TOutputDto>
where TOutputDto : IBaseOutputDto
{
}
并像这样注册:
SearchableServiceFactory<ISearchableLookupService<IBaseOutputDto>, IBaseOutputDto>.Register<OrgLookupService>
(
nameof(Organization), () => new OrgLookupService()
);