ISearchableLookupService

ISearchableLookupService

我正在实现一种工厂模式,并在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>类型不同,因此,即使静态属性也不同。

在编译器看来,它们是不同的类型。仅仅因为OrglookupServiceISearchableLookupService,并不是每个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()
);

10-02 04:20